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(getResourceType())) {
078                        b.append(':');
079                        b.append(getResourceType());
080                }
081                if (isNotBlank(myChain)) {
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                }
096                return myId.getIdPart();
097        }
098
099        @Override
100        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
101                String q = theQualifier;
102                String resourceType = null;
103                if (isNotBlank(q)) {
104                        if (q.startsWith(":")) {
105                                int nextIdx = q.indexOf('.');
106                                if (nextIdx != -1) {
107                                        resourceType = q.substring(1, nextIdx);
108                                        myChain = q.substring(nextIdx + 1);
109                                } else {
110                                        resourceType = q.substring(1);
111                                }
112                        } else if (q.startsWith(".")) {
113                                myChain = q.substring(1);
114                        }
115                }
116
117                setValue(theValue);
118
119                if (isNotBlank(resourceType) && isBlank(getResourceType())) {
120                        setValue(resourceType + '/' + theValue);
121                }
122        }
123
124
125
126        @CoverageIgnore
127        public String getBaseUrl() {
128                return myId.getBaseUrl();
129        }
130
131
132        public String getChain() {
133                return myChain;
134        }
135
136
137        @CoverageIgnore
138        public String getIdPart() {
139                return myId.getIdPart();
140        }
141
142        @CoverageIgnore
143        public BigDecimal getIdPartAsBigDecimal() {
144                return myId.getIdPartAsBigDecimal();
145        }
146        
147        @CoverageIgnore
148        public Long getIdPartAsLong() {
149                return myId.getIdPartAsLong();
150        }
151
152        public String getResourceType() {
153                return myId.getResourceType();
154        }
155
156        public Class<? extends IBaseResource> getResourceType(FhirContext theCtx) {
157                if (isBlank(getResourceType())) {
158                        return null;
159                }
160                return theCtx.getResourceDefinition(getResourceType()).getImplementingClass();
161        }
162
163        public String getValue() {
164                return myId.getValue();
165        }
166
167        public boolean hasResourceType() {
168                return myId.hasResourceType();
169        }
170
171        @Override
172        protected boolean isSupportsChain() {
173                return true;
174        }
175
176        public void setChain(String theChain) {
177                myChain = theChain;
178        }
179
180        public void setValue(String theValue) {
181                myId.setValue(theValue);
182        }
183
184        /**
185         * Returns a new param containing the same value as this param, but with the type copnverted
186         * to {@link DateParam}. This is useful if you are using reference parameters and want to handle
187         * chained parameters of different types in a single method.
188         * <p>
189         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
190         * in the HAPI FHIR documentation for an example of how to use this method.
191         * </p>
192         */
193        public DateParam toDateParam(FhirContext theContext) {
194                DateParam retVal = new DateParam();
195                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
196                return retVal;
197        }
198
199        /**
200         * Returns a new param containing the same value as this param, but with the type copnverted
201         * to {@link NumberParam}. This is useful if you are using reference parameters and want to handle
202         * chained parameters of different types in a single method.
203         * <p>
204         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
205         * in the HAPI FHIR documentation for an example of how to use this method.
206         * </p>
207         */
208        public NumberParam toNumberParam(FhirContext theContext) {
209                NumberParam retVal = new NumberParam();
210                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
211                return retVal;
212        }
213
214        /**
215         * Returns a new param containing the same value as this param, but with the type copnverted
216         * to {@link QuantityParam}. This is useful if you are using reference parameters and want to handle
217         * chained parameters of different types in a single method.
218         * <p>
219         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
220         * in the HAPI FHIR documentation for an example of how to use this method.
221         * </p>
222         */
223        public QuantityParam toQuantityParam(FhirContext theContext) {
224                QuantityParam retVal = new QuantityParam();
225                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
226                return retVal;
227        }
228
229        @Override
230        public String toString() {
231                ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
232                if (isNotBlank(myChain)) {
233                        b.append("chain", myChain);
234                }
235                b.append("value", getValue());
236                return b.build();
237        }
238
239        /**
240         * Returns a new param containing the same value as this param, but with the type copnverted
241         * to {@link StringParam}. This is useful if you are using reference parameters and want to handle
242         * chained parameters of different types in a single method.
243         * <p>
244         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
245         * in the HAPI FHIR documentation for an example of how to use this method.
246         * </p>
247         */
248        public StringParam toStringParam(FhirContext theContext) {
249                StringParam retVal = new StringParam();
250                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
251                return retVal;
252        }
253
254        /**
255         * Returns a new param containing the same value as this param, but with the type copnverted
256         * to {@link TokenParam}. This is useful if you are using reference parameters and want to handle
257         * chained parameters of different types in a single method.
258         * <p>
259         * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a>
260         * in the HAPI FHIR documentation for an example of how to use this method.
261         * </p>
262         */
263        public TokenParam toTokenParam(FhirContext theContext) {
264                TokenParam retVal = new TokenParam();
265                retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext));
266                return retVal;
267        }
268}