001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2018 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                        return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
104                }
105                return ParameterUtil.escape(getValue());
106        }
107
108        /**
109         * {@inheritDoc}
110         */
111        @Override
112        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theParameter) {
113                setModifier(null);
114                if (theQualifier != null) {
115                        TokenParamModifier modifier = TokenParamModifier.forValue(theQualifier);
116                        setModifier(modifier);
117
118                        if (modifier == TokenParamModifier.TEXT) {
119                                setSystem(null);
120                                setValue(ParameterUtil.unescape(theParameter));
121                                return;
122                        }
123                }
124
125                setSystem(null);
126                if (theParameter == null) {
127                        setValue(null);
128                } else {
129                        int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
130                        if (barIndex != -1) {
131                                setSystem(theParameter.substring(0, barIndex));
132                                setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
133                        } else {
134                                setValue(ParameterUtil.unescape(theParameter));
135                        }
136                }
137        }
138
139        /**
140         * Returns the modifier for this token
141         */
142        public TokenParamModifier getModifier() {
143                return myModifier;
144        }
145
146        public TokenParam setModifier(TokenParamModifier theModifier) {
147                myModifier = theModifier;
148                return this;
149        }
150
151        /**
152         * Returns the system for this token. Note that if a {@link #getModifier()} is being used, the entire value of the
153         * parameter will be placed in {@link #getValue() value} and this method will return <code>null</code>.
154         * <p
155         * Also note that this value may be <code>null</code> or <code>""</code> (empty string) and that
156         * each of these have a different meaning. When a token is passed on a URL and it has no
157         * vertical bar (often meaning "return values that match the given code in any codesystem")
158         * this method will return <code>null</code>. When a token is passed on a URL and it has
159         * a vetical bar but nothing before the bar (often meaning "return values that match the
160         * given code but that have no codesystem) this method will return <code>""</code>
161         * </p>
162         */
163        public String getSystem() {
164                return mySystem;
165        }
166
167        public TokenParam setSystem(String theSystem) {
168                mySystem = theSystem;
169                return this;
170        }
171
172        /**
173         * Returns the value for the token (generally the value to the right of the
174         * vertical bar on the URL)
175         */
176        public String getValue() {
177                return myValue;
178        }
179
180        public TokenParam setValue(String theValue) {
181                myValue = theValue;
182                return this;
183        }
184
185        public InternalCodingDt getValueAsCoding() {
186                return new InternalCodingDt(mySystem, myValue);
187        }
188
189        public String getValueNotNull() {
190                return defaultString(myValue);
191        }
192
193        public boolean isEmpty() {
194                return StringUtils.isEmpty(myValue);
195        }
196
197        /**
198         * Returns true if {@link #getModifier()} returns {@link TokenParamModifier#TEXT}
199         */
200        public boolean isText() {
201                return myModifier == TokenParamModifier.TEXT;
202        }
203
204        /**
205         * @deprecated Use {@link #setModifier(TokenParamModifier)} instead
206         */
207        @Deprecated
208        public TokenParam setText(boolean theText) {
209                if (theText) {
210                        myModifier = TokenParamModifier.TEXT;
211                } else {
212                        myModifier = null;
213                }
214                return this;
215        }
216
217        @Override
218        public String toString() {
219                ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
220                builder.append("system", defaultString(getSystem()));
221                if (myModifier != null) {
222                        builder.append(":" + myModifier.getValue());
223                }
224                builder.append("value", getValue());
225                if (getMissing() != null) {
226                        builder.append(":missing", getMissing());
227                }
228                return builder.toString();
229        }
230
231        private static String toSystemValue(UriDt theSystem) {
232                return theSystem.getValueAsString();
233        }
234
235}