001package ca.uhn.fhir.rest.gclient;
002
003import ca.uhn.fhir.context.FhirContext;
004import org.apache.commons.lang3.Validate;
005import org.hl7.fhir.instance.model.api.IIdType;
006
007import java.util.Arrays;
008import java.util.Collection;
009
010import static org.apache.commons.lang3.StringUtils.isNotBlank;
011
012/*
013 * #%L
014 * HAPI FHIR - Core Library
015 * %%
016 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
017 * %%
018 * Licensed under the Apache License, Version 2.0 (the "License");
019 * you may not use this file except in compliance with the License.
020 * You may obtain a copy of the License at
021 *
022 *      http://www.apache.org/licenses/LICENSE-2.0
023 *
024 * Unless required by applicable law or agreed to in writing, software
025 * distributed under the License is distributed on an "AS IS" BASIS,
026 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
027 * See the License for the specific language governing permissions and
028 * limitations under the License.
029 * #L%
030 */
031
032
033public class ReferenceClientParam extends BaseClientParam  implements IParam {
034
035        private String myName;
036
037        public ReferenceClientParam(String theName) {
038                myName = theName;
039        }
040
041        @Override
042        public String getParamName() {
043                return myName;
044        }
045
046        /**
047         * Include a chained search. For example:
048         * <pre>
049         * Bundle resp = ourClient
050         *   .search()
051         *   .forResource(QuestionnaireResponse.class)
052         *   .where(QuestionnaireResponse.SUBJECT.hasChainedProperty(Patient.FAMILY.matches().value("SMITH")))
053         *   .returnBundle(Bundle.class)
054         *   .execute();
055         * </pre>
056         */
057        public ICriterion<ReferenceClientParam> hasChainedProperty(ICriterion<?> theCriterion) {
058                return new ReferenceChainCriterion(getParamName(), theCriterion);
059        }
060
061        /**
062         * Include a chained search with a resource type. For example:
063         * <pre>
064         * Bundle resp = ourClient
065         *   .search()
066         *   .forResource(QuestionnaireResponse.class)
067         *   .where(QuestionnaireResponse.SUBJECT.hasChainedProperty("Patient", Patient.FAMILY.matches().value("SMITH")))
068         *   .returnBundle(Bundle.class)
069         *   .execute();
070         * </pre>
071         */
072        public ICriterion<ReferenceClientParam> hasChainedProperty(String theResourceType, ICriterion<?> theCriterion) {
073                return new ReferenceChainCriterion(getParamName(), theResourceType, theCriterion);
074        }
075
076        /**
077         * Match the referenced resource if the resource has the given ID (this can be
078         * the logical ID or the absolute URL of the resource)
079         */
080        public ICriterion<ReferenceClientParam> hasId(IIdType theId) {
081                return new StringCriterion<>(getParamName(), theId.getValue());
082        }
083
084        /**
085         * Match the referenced resource if the resource has the given ID (this can be
086         * the logical ID or the absolute URL of the resource)
087         */
088        public ICriterion<ReferenceClientParam> hasId(String theId) {
089                return new StringCriterion<>(getParamName(), theId);
090        }
091
092        /**
093         * Match the referenced resource if the resource has ANY of the given IDs
094         * (this is an OR search, not an AND search), (this can be the logical ID or
095         * the absolute URL of the resource). Note that to specify an AND search,
096         * simply add a subsequent {@link IQuery#where(ICriterion) where} criteria
097         * with the same parameter.
098         */
099        public ICriterion<ReferenceClientParam> hasAnyOfIds(Collection<String> theIds) {
100                return new StringCriterion<>(getParamName(), theIds);
101        }
102
103        /**
104         * Match the referenced resource if the resource has ANY of the given IDs
105         * (this is an OR search, not an AND search), (this can be the logical ID or
106         * the absolute URL of the resource). Note that to specify an AND search,
107         * simply add a subsequent {@link IQuery#where(ICriterion) where} criteria
108         * with the same parameter.
109         */
110        public ICriterion<ReferenceClientParam> hasAnyOfIds(String... theIds) {
111                Validate.notNull(theIds, "theIds must not be null");
112                return hasAnyOfIds(Arrays.asList(theIds));
113        }
114
115        private static class ReferenceChainCriterion implements ICriterion<ReferenceClientParam>, ICriterionInternal {
116
117                private final String myResourceTypeQualifier;
118                private String myParamName;
119                private ICriterionInternal myWrappedCriterion;
120
121                ReferenceChainCriterion(String theParamName, ICriterion<?> theWrappedCriterion) {
122                        this(theParamName, null, theWrappedCriterion);
123                }
124
125                ReferenceChainCriterion(String theParamName, String theResourceType, ICriterion<?> theWrappedCriterion) {
126                        myParamName = theParamName;
127                        myResourceTypeQualifier = isNotBlank(theResourceType) ? ":" + theResourceType : "";
128                        myWrappedCriterion = (ICriterionInternal) theWrappedCriterion;
129                }
130
131                @Override
132                public String getParameterName() {
133                        return myParamName + myResourceTypeQualifier + "." + myWrappedCriterion.getParameterName();
134                }
135
136                @Override
137                public String getParameterValue(FhirContext theContext) {
138                        return myWrappedCriterion.getParameterValue(theContext);
139                }
140
141        }
142
143}