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.method;
021
022import ca.uhn.fhir.context.ConfigurationException;
023import ca.uhn.fhir.context.FhirContext;
024import ca.uhn.fhir.context.RuntimeResourceDefinition;
025import ca.uhn.fhir.i18n.Msg;
026import ca.uhn.fhir.model.api.IResource;
027import ca.uhn.fhir.rest.annotation.TransactionParam;
028import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
029import org.hl7.fhir.instance.model.api.IBaseResource;
030
031import java.lang.reflect.Method;
032import java.lang.reflect.Modifier;
033import java.util.Collection;
034import java.util.List;
035import java.util.Map;
036
037public class TransactionParameter implements IParameter {
038
039        // private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TransactionParameter.class);
040        private FhirContext myContext;
041        private ParamStyle myParamStyle;
042
043        public TransactionParameter(FhirContext theContext) {
044                myContext = theContext;
045        }
046
047        private String createParameterTypeError(Method theMethod) {
048                return "Method '" + theMethod.getName() + "' in type '"
049                                + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @"
050                                + TransactionParam.class.getName() + " but is not of type List<" + IResource.class.getCanonicalName()
051                                + "> or Bundle";
052        }
053
054        @Override
055        public void initializeTypes(
056                        Method theMethod,
057                        Class<? extends Collection<?>> theOuterCollectionType,
058                        Class<? extends Collection<?>> theInnerCollectionType,
059                        Class<?> theParameterType) {
060                if (theOuterCollectionType != null) {
061                        throw new ConfigurationException(Msg.code(1454) + "Method '" + theMethod.getName() + "' in type '"
062                                        + theMethod.getDeclaringClass().getCanonicalName() + "' is annotated with @"
063                                        + TransactionParam.class.getName() + " but can not be a collection of collections");
064                }
065                if (Modifier.isInterface(theParameterType.getModifiers()) == false
066                                && IBaseResource.class.isAssignableFrom(theParameterType)) {
067                        @SuppressWarnings("unchecked")
068                        Class<? extends IBaseResource> parameterType = (Class<? extends IBaseResource>) theParameterType;
069                        RuntimeResourceDefinition def = myContext.getResourceDefinition(parameterType);
070                        if ("Bundle".equals(def.getName())) {
071                                myParamStyle = ParamStyle.RESOURCE_BUNDLE;
072                        } else {
073                                throw new ConfigurationException(Msg.code(1455) + createParameterTypeError(theMethod));
074                        }
075                } else {
076                        if (theInnerCollectionType.equals(List.class) == false) {
077                                throw new ConfigurationException(Msg.code(1456) + createParameterTypeError(theMethod));
078                        }
079                        if (theParameterType.equals(IResource.class) == false
080                                        && theParameterType.equals(IBaseResource.class) == false) {
081                                throw new ConfigurationException(Msg.code(1457) + createParameterTypeError(theMethod));
082                        }
083                        myParamStyle = ParamStyle.RESOURCE_LIST;
084                }
085        }
086
087        @Override
088        public void translateClientArgumentIntoQueryArgument(
089                        FhirContext theContext,
090                        Object theSourceClientArgument,
091                        Map<String, List<String>> theTargetQueryArguments,
092                        IBaseResource theTargetResource)
093                        throws InternalErrorException {
094                // nothing
095
096        }
097
098        public ParamStyle getParamStyle() {
099                return myParamStyle;
100        }
101
102        public enum ParamStyle {
103                /** New style bundle (defined in hapi-fhir-structures-* as a resource definition itself */
104                RESOURCE_BUNDLE,
105                /** List of resources */
106                RESOURCE_LIST
107        }
108}