001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2017 University Health Network
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 */
022import static org.apache.commons.lang3.StringUtils.isBlank;
023import static org.apache.commons.lang3.StringUtils.isNotBlank;
024
025import java.math.BigDecimal;
026
027import org.apache.commons.lang3.builder.ToStringBuilder;
028import org.apache.commons.lang3.builder.ToStringStyle;
029import org.hl7.fhir.instance.model.api.IBaseResource;
030
031import ca.uhn.fhir.context.FhirContext;
032import ca.uhn.fhir.model.primitive.IdDt;
033import ca.uhn.fhir.util.CoverageIgnore;
034
035public class ReferenceParam extends BaseParam /*implements IQueryParameterType*/ {
036
037        private String myChain;
038
039        private final IdDt myId = new IdDt();
040        /**
041         * Constructor
042         */
043        public ReferenceParam() {
044                super();
045        }
046
047        /**
048         * Constructor
049         */
050        public ReferenceParam(String theValue) {
051                setValueAsQueryToken(null, null, null, theValue);
052        }
053
054        /**
055         * Constructor
056         */
057        public ReferenceParam(String theChain, String theValue) {
058                setValueAsQueryToken(null, null, null, theValue);
059                setChain(theChain);
060        }
061
062        /**
063         * Constructor
064         */
065        public ReferenceParam(String theResourceType, String theChain, String theValue) {
066                if (isNotBlank(theResourceType)) {
067                        setValue(theResourceType + "/" + theValue);
068                } else {
069                        setValue(theValue);
070                }
071                setChain(theChain);
072        }
073
074        @Override
075        String doGetQueryParameterQualifier() {
076                StringBuilder b = new StringBuilder();
077                if (isNotBlank(myChain)) {
078                        if (isNotBlank(getResourceType())) {
079                                b.append(':');
080                                b.append(getResourceType());
081                        }
082                        b.append('.');
083                        b.append(myChain);
084                }
085                if (b.length() != 0) {
086                        return b.toString();
087                }
088                return null;
089        }
090
091        @Override
092        String doGetValueAsQueryToken(FhirContext theContext) {
093                if (isBlank(myId.getResourceType())) {
094                        return myId.getValue(); // e.g. urn:asdjd or 123 or cid:wieiuru or #1
095                } else {
096                        if (isBlank(getChain())) {
097                                return getResourceType() + "/" + myId.getIdPart();
098                        }
099                        return myId.getIdPart();
100                }
101        }
102
103        @Override
104        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
105                String q = theQualifier;
106                String resourceType = null;
107                if (isNotBlank(q)) {
108                        if (q.startsWith(":")) {
109                                int nextIdx = q.indexOf('.');
110                                if (nextIdx != -1) {
111                                        resourceType = q.substring(1, nextIdx);
112                                        myChain = q.substring(nextIdx + 1);
113                                } else {
114                                        resourceType = q.substring(1);
115                                }
116                        } else if (q.startsWith(".")) {
117                                myChain = q.substring(1);
118                        }
119                }
120
121                setValue(theValue);
122
123                if (isNotBlank(resourceType) && isBlank(getResourceType())) {
124                        setValue(resourceType + '/' + theValue);
125                }
126        }
127
128
129
130        @CoverageIgnore
131        public String getBaseUrl() {
132                return myId.getBaseUrl();
133        }
134
135
136        public String getChain() {
137                return myChain;
138        }
139
140
141        @CoverageIgnore
142        public String getIdPart() {
143                return myId.getIdPart();
144        }
145
146        @CoverageIgnore
147        public BigDecimal getIdPartAsBigDecimal() {
148                return myId.getIdPartAsBigDecimal();
149        }
150        
151        @CoverageIgnore
152        public Long getIdPartAsLong() {
153                return myId.getIdPartAsLong();
154        }
155
156        public String getResourceType() {
157                return myId.getResourceType();
158        }
159
160        public Class<? extends IBaseResource> getResourceType(FhirContext theCtx) {
161                if (isBlank(getResourceType())) {
162                        return null;
163                }
164                return theCtx.getResourceDefinition(getResourceType()).getImplementingClass();
165        }
166
167        public String getValue() {
168                return myId.getValue();
169        }
170
171        public boolean hasResourceType() {
172                return myId.hasResourceType();
173        }
174
175        @Override
176        protected boolean isSupportsChain() {
177                return true;
178        }
179
180        public ReferenceParam setChain(String theChain) {
181                myChain = theChain;
182                return this;
183        }
184
185        public ReferenceParam setValue(String theValue) {
186                myId.setValue(theValue);
187                return this;
188        }
189
190        /**
191         * Returns a new param containing the same value as this param, but with the type copnverted
192         * to {@link DateParam}. This is useful if you are using reference parameters and want to handle
193         * chained parameters of different types in a single method.
194         * <p>
195         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
196         * in the HAPI FHIR documentation for an example of how to use this method.
197         * </p>
198         */
199        public DateParam toDateParam(FhirContext theContext) {
200                DateParam retVal = new DateParam();
201                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
202                return retVal;
203        }
204
205        /**
206         * Returns a new param containing the same value as this param, but with the type copnverted
207         * to {@link NumberParam}. This is useful if you are using reference parameters and want to handle
208         * chained parameters of different types in a single method.
209         * <p>
210         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
211         * in the HAPI FHIR documentation for an example of how to use this method.
212         * </p>
213         */
214        public NumberParam toNumberParam(FhirContext theContext) {
215                NumberParam retVal = new NumberParam();
216                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
217                return retVal;
218        }
219
220        /**
221         * Returns a new param containing the same value as this param, but with the type copnverted
222         * to {@link QuantityParam}. This is useful if you are using reference parameters and want to handle
223         * chained parameters of different types in a single method.
224         * <p>
225         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
226         * in the HAPI FHIR documentation for an example of how to use this method.
227         * </p>
228         */
229        public QuantityParam toQuantityParam(FhirContext theContext) {
230                QuantityParam retVal = new QuantityParam();
231                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
232                return retVal;
233        }
234
235        @Override
236        public String toString() {
237                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
238                if (isNotBlank(myChain)) {
239                        b.append("chain", myChain);
240                }
241                b.append("value", getValue());
242                return b.build();
243        }
244
245        /**
246         * Returns a new param containing the same value as this param, but with the type copnverted
247         * to {@link StringParam}. This is useful if you are using reference parameters and want to handle
248         * chained parameters of different types in a single method.
249         * <p>
250         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
251         * in the HAPI FHIR documentation for an example of how to use this method.
252         * </p>
253         */
254        public StringParam toStringParam(FhirContext theContext) {
255                StringParam retVal = new StringParam();
256                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
257                return retVal;
258        }
259
260        /**
261         * Returns a new param containing the same value as this param, but with the type copnverted
262         * to {@link TokenParam}. This is useful if you are using reference parameters and want to handle
263         * chained parameters of different types in a single method.
264         * <p>
265         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
266         * in the HAPI FHIR documentation for an example of how to use this method.
267         * </p>
268         */
269        public TokenParam toTokenParam(FhirContext theContext) {
270                TokenParam retVal = new TokenParam();
271                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
272                return retVal;
273        }
274}