001package ca.uhn.fhir.rest.server.method;
002
003/*
004 * #%L
005 * HAPI FHIR - Server 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.context.FhirContext;
024import ca.uhn.fhir.rest.api.QualifiedParamList;
025import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
026import ca.uhn.fhir.rest.api.server.RequestDetails;
027import ca.uhn.fhir.rest.param.QualifierDetails;
028import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
029import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
030
031import java.lang.reflect.Method;
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.List;
035import java.util.Set;
036
037public abstract class BaseQueryParameter implements IParameter {
038
039        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseQueryParameter.class);
040
041        public abstract List<QualifiedParamList> encode(FhirContext theContext, Object theObject) throws InternalErrorException;
042
043        public abstract String getName();
044
045        public abstract RestSearchParameterTypeEnum getParamType();
046
047        /**
048         * Returns null if blacklist is "none"
049         */
050        public Set<String> getQualifierBlacklist() {
051                return null;
052        }
053
054        /**
055         * Returns null if whitelist is "all"
056         */
057        public Set<String> getQualifierWhitelist() {
058                return null;
059        }
060
061        protected abstract boolean supportsRepetition();
062
063        /**
064         * Parameter should return true if {@link #parse(FhirContext, List)} should be called even if the query string
065         * contained no values for the given parameter
066         */
067        public abstract boolean handlesMissing();
068
069        @Override
070        public void initializeTypes(Method theMethod, Class<? extends Collection<?>> theOuterCollectionType, Class<? extends Collection<?>> theInnerCollectionType, Class<?> theParameterType) {
071                // ignore for now
072        }
073
074        public abstract boolean isRequired();
075
076        public abstract Object parse(FhirContext theContext, List<QualifiedParamList> theString) throws InternalErrorException, InvalidRequestException;
077
078        private void parseParams(RequestDetails theRequest, List<QualifiedParamList> paramList, String theQualifiedParamName, String theQualifier) {
079                QualifierDetails qualifiers = QualifierDetails.extractQualifiersFromParameterName(theQualifier);
080                if (!qualifiers.passes(getQualifierWhitelist(), getQualifierBlacklist())) {
081                        return;
082                }
083
084                String[] value = theRequest.getParameters().get(theQualifiedParamName);
085                if (value != null) {
086                        for (String nextParam : value) {
087                                if (nextParam.contains(",") == false) {
088                                        paramList.add(QualifiedParamList.singleton(theQualifier, nextParam));
089                                } else {
090                                        paramList.add(QualifiedParamList.splitQueryStringByCommasIgnoreEscape(theQualifier, nextParam));
091                                }
092                        }
093                }
094        }
095
096
097        @Override
098        public Object translateQueryParametersIntoServerArgument(RequestDetails theRequest, BaseMethodBinding<?> theMethodBinding) throws InternalErrorException, InvalidRequestException {
099
100                List<QualifiedParamList> paramList = new ArrayList<>();
101                String name = getName();
102                parseParams(theRequest, paramList, name, null);
103
104                List<String> qualified = theRequest.getUnqualifiedToQualifiedNames().get(name);
105                if (qualified != null) {
106                        for (String nextQualified : qualified) {
107                                parseParams(theRequest, paramList, nextQualified, nextQualified.substring(name.length()));
108                        }
109                }
110
111                if (paramList.isEmpty()) {
112
113                        ourLog.debug("No value for parameter '{}' - Qualified names {} and qualifier whitelist {}", new Object[] { getName(), qualified, getQualifierWhitelist() });
114
115                        if (handlesMissing()) {
116                                return parse(theRequest.getFhirContext(), paramList);
117                        }
118                        return null;
119                }
120
121                return parse(theRequest.getFhirContext(), paramList);
122
123        }
124
125}