001package ca.uhn.fhir.rest.client.method;
002
003/*-
004 * #%L
005 * HAPI FHIR - Client Framework
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.i18n.Msg;
024import java.lang.reflect.Method;
025import java.lang.reflect.Modifier;
026import java.util.*;
027
028import org.hl7.fhir.instance.model.api.IBaseResource;
029
030import ca.uhn.fhir.context.*;
031import ca.uhn.fhir.model.api.IResource;
032import ca.uhn.fhir.rest.annotation.TransactionParam;
033import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
034
035public class TransactionParameter implements IParameter {
036
037        // private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionParameter.class);
038        private FhirContext myContext;
039        private ParamStyle myParamStyle;
040
041        public TransactionParameter(FhirContext theContext) {
042                myContext = theContext;
043        }
044
045        private String createParameterTypeError(Method theMethod) {
046                return "Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @" + TransactionParam.class.getName()
047                                + " but is not of type List<" + IResource.class.getCanonicalName() + "> or Bundle";
048        }
049
050        @Override
051        public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
052                if (theOuterCollectionType != null) {
053                        throw new ConfigurationException(Msg.code(1454) + "Method '" + theMethod.getName() + "' in type '" + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @"
054                                        + TransactionParam.class.getName() + " but can not be a collection of collections");
055                }
056                if (Modifier.isInterface(theParameterType.getModifiers()) == false && IBaseResource.class.isAssignableFrom(theParameterType)) {
057                        @SuppressWarnings("unchecked")
058                        Class<? extends IBaseResource> parameterType = (Class<? extends IBaseResource>) theParameterType;
059                        RuntimeResourceDefinition def = myContext.getResourceDefinition(parameterType);
060                        if ("Bundle".equals(def.getName())) {
061                                myParamStyle = ParamStyle.RESOURCE_BUNDLE;
062                        } else {
063                                throw new ConfigurationException(Msg.code(1455) + createParameterTypeError(theMethod));
064                        }
065                } else {
066                        if (theInnerCollectionType.equals(List.class) == false) {
067                                throw new ConfigurationException(Msg.code(1456) + createParameterTypeError(theMethod));
068                        }
069                        if (theParameterType.equals(IResource.class) == false && theParameterType.equals(IBaseResource.class) == false) {
070                                throw new ConfigurationException(Msg.code(1457) + createParameterTypeError(theMethod));
071                        }
072                        myParamStyle = ParamStyle.RESOURCE_LIST;
073                }
074        }
075
076        @Override
077        public void translateClientArgumentIntoQueryArgument(FhirContext theContext, Object theSourceClientArgument, Map<String, List<String>> theTargetQueryArguments, IBaseResource theTargetResource)
078                        throws InternalErrorException {
079                // nothing
080
081        }
082
083        public ParamStyle getParamStyle() {
084                return myParamStyle;
085        }
086
087        public enum ParamStyle {
088                /** New style bundle (defined in hapi-fhir-structures-* as a resource definition itself */
089                RESOURCE_BUNDLE,
090                /** List of resources */
091                RESOURCE_LIST
092        }
093
094}