001/*-
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.interceptor.executor;
021
022import ca.uhn.fhir.interceptor.api.Hook;
023import ca.uhn.fhir.interceptor.api.HookParams;
024import ca.uhn.fhir.interceptor.api.IAnonymousInterceptor;
025import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
026import ca.uhn.fhir.interceptor.api.IInterceptorService;
027import ca.uhn.fhir.interceptor.api.Interceptor;
028import ca.uhn.fhir.interceptor.api.Pointcut;
029import com.google.common.annotations.VisibleForTesting;
030import org.apache.commons.lang3.Validate;
031
032import java.lang.reflect.Method;
033import java.util.Optional;
034
035public class InterceptorService extends BaseInterceptorService<Pointcut>
036                implements IInterceptorService, IInterceptorBroadcaster {
037
038        /**
039         * Constructor which uses a default name of "default"
040         */
041        public InterceptorService() {
042                this("default");
043        }
044
045        /**
046         * Constructor
047         *
048         * @param theName The name for this registry (useful for troubleshooting)
049         */
050        public InterceptorService(String theName) {
051                super(Pointcut.class, theName);
052        }
053
054        @Override
055        protected Optional<HookDescriptor> scanForHook(Method nextMethod) {
056                return findAnnotation(nextMethod, Hook.class).map(t -> new HookDescriptor(t.value(), t.order()));
057        }
058
059        @Override
060        @VisibleForTesting
061        public void registerAnonymousInterceptor(Pointcut thePointcut, IAnonymousInterceptor theInterceptor) {
062                registerAnonymousInterceptor(thePointcut, Interceptor.DEFAULT_ORDER, theInterceptor);
063        }
064
065        @Override
066        public void registerAnonymousInterceptor(Pointcut thePointcut, int theOrder, IAnonymousInterceptor theInterceptor) {
067                Validate.notNull(thePointcut, "thePointcut must not be null");
068                Validate.notNull(theInterceptor, "theInterceptor must not be null");
069                BaseInvoker invoker = new AnonymousLambdaInvoker(thePointcut, theInterceptor, theOrder);
070                registerAnonymousInterceptor(thePointcut, theInterceptor, invoker);
071        }
072
073        private static class AnonymousLambdaInvoker extends BaseInvoker {
074                private final IAnonymousInterceptor myHook;
075                private final Pointcut myPointcut;
076
077                public AnonymousLambdaInvoker(Pointcut thePointcut, IAnonymousInterceptor theHook, int theOrder) {
078                        super(theHook, theOrder);
079                        myHook = theHook;
080                        myPointcut = thePointcut;
081                }
082
083                @Override
084                public Object invoke(HookParams theParams) {
085                        myHook.invoke(myPointcut, theParams);
086                        return true;
087                }
088        }
089}