001/*
002 * #%L
003 * HAPI FHIR - Client Framework
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.rest.client.impl;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.rest.client.api.IHttpClient;
025import ca.uhn.fhir.rest.client.impl.ClientInvocationHandlerFactory.ILambda;
026import ca.uhn.fhir.rest.client.method.BaseMethodBinding;
027
028import java.lang.reflect.InvocationHandler;
029import java.lang.reflect.Method;
030import java.util.Map;
031
032public class ClientInvocationHandler extends BaseClient implements InvocationHandler {
033
034        private final Map<Method, BaseMethodBinding<?>> myBindings;
035        private final Map<Method, Object> myMethodToReturnValue;
036        private FhirContext myContext;
037        private Map<Method, ILambda> myMethodToLambda;
038
039        public ClientInvocationHandler(
040                        IHttpClient theClient,
041                        FhirContext theContext,
042                        String theUrlBase,
043                        Map<Method, Object> theMethodToReturnValue,
044                        Map<Method, BaseMethodBinding<?>> theBindings,
045                        Map<Method, ILambda> theMethodToLambda,
046                        RestfulClientFactory theFactory) {
047                super(theClient, theUrlBase, theFactory);
048
049                myContext = theContext;
050                myMethodToReturnValue = theMethodToReturnValue;
051                myBindings = theBindings;
052                myMethodToLambda = theMethodToLambda;
053        }
054
055        public void addBinding(Method theMethod, BaseMethodBinding<?> theBinding) {
056                myBindings.put(theMethod, theBinding);
057        }
058
059        @Override
060        public Object invoke(Object theProxy, Method theMethod, Object[] theArgs) throws Throwable {
061                Object directRetVal = myMethodToReturnValue.get(theMethod);
062                if (directRetVal != null) {
063                        return directRetVal;
064                }
065
066                BaseMethodBinding<?> binding = myBindings.get(theMethod);
067                if (binding != null) {
068                        BaseHttpClientInvocation clientInvocation = binding.invokeClient(theArgs);
069                        return invokeClient(myContext, binding, clientInvocation);
070                }
071
072                ILambda lambda = myMethodToLambda.get(theMethod);
073                if (lambda != null) {
074                        return lambda.handle(this, theArgs);
075                }
076
077                throw new UnsupportedOperationException(Msg.code(1403) + "The method '" + theMethod.getName() + "' in type "
078                                + theMethod.getDeclaringClass().getSimpleName()
079                                + " has no handler. Did you forget to annotate it with a RESTful method annotation?");
080        }
081
082        @Override
083        public FhirContext getFhirContext() {
084                return myContext;
085        }
086}