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