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