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