001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2021 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.model.base.composite.BaseCodingDt;
025import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
026import ca.uhn.fhir.model.primitive.UriDt;
027import org.apache.commons.lang3.StringUtils;
028import org.apache.commons.lang3.builder.EqualsBuilder;
029import org.apache.commons.lang3.builder.HashCodeBuilder;
030import org.apache.commons.lang3.builder.ToStringBuilder;
031import org.apache.commons.lang3.builder.ToStringStyle;
032import org.hl7.fhir.instance.model.api.IBaseCoding;
033
034import static org.apache.commons.lang3.StringUtils.defaultString;
035import static org.apache.commons.lang3.StringUtils.isNotBlank;
036
037public class TokenParam extends BaseParam /*implements IQueryParameterType*/ {
038
039        private TokenParamModifier myModifier;
040        private String mySystem;
041        private String myValue;
042
043        /**
044         * Constructor
045         */
046        public TokenParam() {
047                super();
048        }
049
050        /**
051         * Constructor which copies the {@link InternalCodingDt#getSystemElement() system} and
052         * {@link InternalCodingDt#getCodeElement() code} from a {@link InternalCodingDt} instance and adds it as a parameter
053         *
054         * @param theCodingDt The coding
055         */
056        public TokenParam(BaseCodingDt theCodingDt) {
057                this(toSystemValue(theCodingDt.getSystemElement()), theCodingDt.getCodeElement().getValue());
058        }
059
060        /**
061         * Constructor which copies the {@link BaseIdentifierDt#getSystemElement() system} and
062         * {@link BaseIdentifierDt#getValueElement() value} from a {@link BaseIdentifierDt} instance and adds it as a
063         * parameter
064         *
065         * @param theIdentifierDt The identifier
066         */
067        public TokenParam(BaseIdentifierDt theIdentifierDt) {
068                this(toSystemValue(theIdentifierDt.getSystemElement()), theIdentifierDt.getValueElement().getValue());
069        }
070
071        /**
072         * Construct a {@link TokenParam} from the {@link IBaseCoding#getSystem()} () system} and
073         * {@link IBaseCoding#getCode()} () code} of a {@link IBaseCoding} instance.
074         *
075         * @param theCoding The coding
076         */
077        public TokenParam(IBaseCoding theCoding) {
078                this(theCoding.getSystem(), theCoding.getCode());
079        }
080
081        public TokenParam(String theSystem, String theValue) {
082                setSystem(theSystem);
083                setValue(theValue);
084        }
085
086        public TokenParam(String theSystem, String theValue, boolean theText) {
087                if (theText && isNotBlank(theSystem)) {
088                        throw new IllegalArgumentException("theSystem can not be non-blank if theText is true (:text searches do not include a system). In other words, set the first parameter to null for a text search");
089                }
090                setSystem(theSystem);
091                setValue(theValue);
092                setText(theText);
093        }
094
095        /**
096         * Constructor that takes a code but no system
097         */
098        public TokenParam(String theCode) {
099                this(null, theCode);
100        }
101
102        @Override
103        String doGetQueryParameterQualifier() {
104                if (getModifier() != null) {
105                        return getModifier().getValue();
106                }
107                return null;
108        }
109
110        /**
111         * {@inheritDoc}
112         */
113        @Override
114        String doGetValueAsQueryToken(FhirContext theContext) {
115                if (getSystem() != null) {
116                        if (getValue() != null) {
117                                return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
118                        } else {
119                                return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|';
120                        }
121                }
122                return ParameterUtil.escape(getValue());
123        }
124
125        /**
126         * {@inheritDoc}
127         */
128        @Override
129        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theParameter) {
130                setModifier(null);
131                if (theQualifier != null) {
132                        TokenParamModifier modifier = TokenParamModifier.forValue(theQualifier);
133                        setModifier(modifier);
134
135                        if (modifier == TokenParamModifier.TEXT) {
136                                setSystem(null);
137                                setValue(ParameterUtil.unescape(theParameter));
138                                return;
139                        }
140                }
141
142                setSystem(null);
143                if (theParameter == null) {
144                        setValue(null);
145                } else {
146                        int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
147                        if (barIndex != -1) {
148                                setSystem(theParameter.substring(0, barIndex));
149                                setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
150                        } else {
151                                setValue(ParameterUtil.unescape(theParameter));
152                        }
153                }
154        }
155
156        /**
157         * Returns the modifier for this token
158         */
159        public TokenParamModifier getModifier() {
160                return myModifier;
161        }
162
163        public TokenParam setModifier(TokenParamModifier theModifier) {
164                myModifier = theModifier;
165                return this;
166        }
167
168        /**
169         * Returns the system for this token. Note that if a {@link #getModifier()} is being used, the entire value of the
170         * parameter will be placed in {@link #getValue() value} and this method will return <code>null</code>.
171         * <p
172         * Also note that this value may be <code>null</code> or <code>""</code> (empty string) and that
173         * each of these have a different meaning. When a token is passed on a URL and it has no
174         * vertical bar (often meaning "return values that match the given code in any codesystem")
175         * this method will return <code>null</code>. When a token is passed on a URL and it has
176         * a vetical bar but nothing before the bar (often meaning "return values that match the
177         * given code but that have no codesystem) this method will return <code>""</code>
178         * </p>
179         */
180        public String getSystem() {
181                return mySystem;
182        }
183
184        public TokenParam setSystem(String theSystem) {
185                mySystem = theSystem;
186                return this;
187        }
188
189        /**
190         * Returns the value for the token (generally the value to the right of the
191         * vertical bar on the URL)
192         */
193        public String getValue() {
194                return myValue;
195        }
196
197        public TokenParam setValue(String theValue) {
198                myValue = theValue;
199                return this;
200        }
201
202        public InternalCodingDt getValueAsCoding() {
203                return new InternalCodingDt(mySystem, myValue);
204        }
205
206        public String getValueNotNull() {
207                return defaultString(myValue);
208        }
209
210        public boolean isEmpty() {
211                return StringUtils.isBlank(mySystem) && StringUtils.isBlank(myValue) && getMissing() == null;
212        }
213
214        /**
215         * Returns true if {@link #getModifier()} returns {@link TokenParamModifier#TEXT}
216         */
217        public boolean isText() {
218                return myModifier == TokenParamModifier.TEXT;
219        }
220
221        /**
222         * @deprecated Use {@link #setModifier(TokenParamModifier)} instead
223         */
224        @Deprecated
225        public TokenParam setText(boolean theText) {
226                if (theText) {
227                        myModifier = TokenParamModifier.TEXT;
228                } else {
229                        myModifier = null;
230                }
231                return this;
232        }
233
234
235        @Override
236        public String toString() {
237                ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
238                builder.append("system", defaultString(getSystem()));
239                if (myModifier != null) {
240                        builder.append(":" + myModifier.getValue());
241                }
242                builder.append("value", getValue());
243                if (getMissing() != null) {
244                        builder.append(":missing", getMissing());
245                }
246                return builder.toString();
247        }
248
249        @Override
250        public boolean equals(Object theO) {
251                if (this == theO) {
252                        return true;
253                }
254
255                if (theO == null || getClass() != theO.getClass()) {
256                        return false;
257                }
258
259                TokenParam that = (TokenParam) theO;
260
261                EqualsBuilder b = new EqualsBuilder();
262                b.append(myModifier, that.myModifier);
263                b.append(mySystem, that.mySystem);
264                b.append(myValue, that.myValue);
265                return b.isEquals();
266        }
267
268        @Override
269        public int hashCode() {
270                HashCodeBuilder b = new HashCodeBuilder(17, 37);
271                b.append(myModifier);
272                b.append(mySystem);
273                b.append(myValue);
274                return b.toHashCode();
275        }
276
277        private static String toSystemValue(UriDt theSystem) {
278                return theSystem.getValueAsString();
279        }
280
281}