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.ConfigurationException;
023import ca.uhn.fhir.context.FhirContext;
024import ca.uhn.fhir.i18n.Msg;
025import ca.uhn.fhir.rest.api.EncodingEnum;
026import ca.uhn.fhir.rest.api.SummaryEnum;
027import ca.uhn.fhir.rest.client.api.IHttpClient;
028import ca.uhn.fhir.rest.client.api.IRestfulClient;
029import ca.uhn.fhir.rest.client.method.BaseMethodBinding;
030import org.hl7.fhir.instance.model.api.IBaseResource;
031
032import java.lang.reflect.Method;
033import java.util.HashMap;
034import java.util.Map;
035
036public class ClientInvocationHandlerFactory {
037
038        private final Map<Method, BaseMethodBinding<?>> myBindings = new HashMap<Method, BaseMethodBinding<?>>();
039        private final IHttpClient myClient;
040        private final FhirContext myContext;
041        private final Map<Method, ILambda> myMethodToLambda = new HashMap<Method, ILambda>();
042        private final Map<Method, Object> myMethodToReturnValue = new HashMap<Method, Object>();
043        private final String myUrlBase;
044
045        public ClientInvocationHandlerFactory(
046                        IHttpClient theClient,
047                        FhirContext theContext,
048                        String theUrlBase,
049                        Class<? extends IRestfulClient> theClientType) {
050                myClient = theClient;
051                myUrlBase = theUrlBase;
052                myContext = theContext;
053
054                try {
055                        myMethodToReturnValue.put(theClientType.getMethod("getFhirContext"), theContext);
056                        myMethodToReturnValue.put(theClientType.getMethod("getHttpClient"), theClient);
057                        myMethodToReturnValue.put(theClientType.getMethod("getServerBase"), theUrlBase);
058
059                        myMethodToLambda.put(theClientType.getMethod("setEncoding", EncodingEnum.class), new SetEncodingLambda());
060                        myMethodToLambda.put(theClientType.getMethod("setPrettyPrint", Boolean.class), new SetPrettyPrintLambda());
061                        myMethodToLambda.put(
062                                        theClientType.getMethod("registerInterceptor", Object.class), new RegisterInterceptorLambda());
063                        myMethodToLambda.put(
064                                        theClientType.getMethod("unregisterInterceptor", Object.class), new UnregisterInterceptorLambda());
065                        myMethodToLambda.put(theClientType.getMethod("setSummary", SummaryEnum.class), new SetSummaryLambda());
066                        myMethodToLambda.put(
067                                        theClientType.getMethod("fetchResourceFromUrl", Class.class, String.class),
068                                        new FetchResourceFromUrlLambda());
069
070                } catch (NoSuchMethodException e) {
071                        throw new ConfigurationException(
072                                        Msg.code(1352) + "Failed to find methods on client. This is a HAPI bug!", e);
073                } catch (SecurityException e) {
074                        throw new ConfigurationException(
075                                        Msg.code(1353) + "Failed to find methods on client. This is a HAPI bug!", e);
076                }
077        }
078
079        public void addBinding(Method theMethod, BaseMethodBinding<?> theBinding) {
080                myBindings.put(theMethod, theBinding);
081        }
082
083        ClientInvocationHandler newInvocationHandler(RestfulClientFactory theRestfulClientFactory) {
084                return new ClientInvocationHandler(
085                                myClient,
086                                myContext,
087                                myUrlBase,
088                                myMethodToReturnValue,
089                                myBindings,
090                                myMethodToLambda,
091                                theRestfulClientFactory);
092        }
093
094        public interface ILambda {
095                Object handle(ClientInvocationHandler theTarget, Object[] theArgs);
096        }
097
098        class RegisterInterceptorLambda implements ILambda {
099                @Override
100                public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
101                        Object interceptor = theArgs[0];
102                        theTarget.registerInterceptor(interceptor);
103                        return null;
104                }
105        }
106
107        class FetchResourceFromUrlLambda implements ILambda {
108                @Override
109                public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
110                        @SuppressWarnings("unchecked")
111                        Class<? extends IBaseResource> type = (Class<? extends IBaseResource>) theArgs[0];
112                        String url = (String) theArgs[1];
113
114                        return theTarget.fetchResourceFromUrl(type, url);
115                }
116        }
117
118        class SetEncodingLambda implements ILambda {
119                @Override
120                public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
121                        EncodingEnum encoding = (EncodingEnum) theArgs[0];
122                        theTarget.setEncoding(encoding);
123                        return null;
124                }
125        }
126
127        class SetPrettyPrintLambda implements ILambda {
128                @Override
129                public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
130                        Boolean prettyPrint = (Boolean) theArgs[0];
131                        theTarget.setPrettyPrint(prettyPrint);
132                        return null;
133                }
134        }
135
136        class SetSummaryLambda implements ILambda {
137                @Override
138                public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
139                        SummaryEnum encoding = (SummaryEnum) theArgs[0];
140                        theTarget.setSummary(encoding);
141                        return null;
142                }
143        }
144
145        class UnregisterInterceptorLambda implements ILambda {
146                @Override
147                public Object handle(ClientInvocationHandler theTarget, Object[] theArgs) {
148                        Object interceptor = theArgs[0];
149                        theTarget.unregisterInterceptor(interceptor);
150                        return null;
151                }
152        }
153}