001package ca.uhn.fhir.rest.param;
002
003/*
004 * #%L
005 * HAPI FHIR - Core Library
006 * %%
007 * Copyright (C) 2014 - 2017 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.defaultString;
023import static org.apache.commons.lang3.StringUtils.isNotBlank;
024
025import org.apache.commons.lang3.StringUtils;
026import org.apache.commons.lang3.builder.ToStringBuilder;
027import org.apache.commons.lang3.builder.ToStringStyle;
028
029import ca.uhn.fhir.context.FhirContext;
030import ca.uhn.fhir.model.base.composite.BaseCodingDt;
031import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
032import ca.uhn.fhir.model.primitive.UriDt;
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
052         *           The coding
053         */
054        public TokenParam(BaseCodingDt theCodingDt) {
055                this(toSystemValue(theCodingDt.getSystemElement()), theCodingDt.getCodeElement().getValue());
056        }
057
058        /**
059         * Constructor which copies the {@link BaseIdentifierDt#getSystemElement() system} and
060         * {@link BaseIdentifierDt#getValueElement() value} from a {@link BaseIdentifierDt} instance and adds it as a
061         * parameter
062         * 
063         * @param theIdentifierDt
064         *           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        @Override
085        String doGetQueryParameterQualifier() {
086                if (getModifier() != null) {
087                        return getModifier().getValue();
088                }
089                return null;
090        }
091
092        /**
093         * {@inheritDoc}
094         */
095        @Override
096        String doGetValueAsQueryToken(FhirContext theContext) {
097                if (getSystem() != null) {
098                        return ParameterUtil.escape(StringUtils.defaultString(getSystem())) + '|' + ParameterUtil.escape(getValue());
099                }
100                return ParameterUtil.escape(getValue());
101        }
102
103        /**
104         * {@inheritDoc}
105         */
106        @Override
107        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theParameter) {
108                setModifier(null);
109                if (theQualifier != null) {
110                        TokenParamModifier modifier = TokenParamModifier.forValue(theQualifier);
111                        setModifier(modifier);
112                        
113                        if (modifier == TokenParamModifier.TEXT) {
114                                setSystem(null);
115                                setValue(ParameterUtil.unescape(theParameter));
116                                return;
117                        }
118                }
119
120                setSystem(null);
121                if (theParameter == null) {
122                        setValue(null);
123                } else {
124                        int barIndex = ParameterUtil.nonEscapedIndexOf(theParameter, '|');
125                        if (barIndex != -1) {
126                                setSystem(theParameter.substring(0, barIndex));
127                                setValue(ParameterUtil.unescape(theParameter.substring(barIndex + 1)));
128                        } else {
129                                setValue(ParameterUtil.unescape(theParameter));
130                        }
131                }
132        }
133
134        /**
135         * Returns the modifier for this token
136         */
137        public TokenParamModifier getModifier() {
138                return myModifier;
139        }
140
141        /**
142         * Returns the system for this token. Note that if a {@link #getModifier()} is being used, the entire value of the
143         * parameter will be placed in {@link #getValue() value} and this method will return <code>null</code>. 
144         * <p
145         * Also note that this value may be <code>null</code> or <code>""</code> (empty string) and that
146         * each of these have a different meaning. When a token is passed on a URL and it has no
147         * vertical bar (often meaning "return values that match the given code in any codesystem") 
148         * this method will return <code>null</code>. When a token is passed on a URL and it has
149         * a vetical bar but nothing before the bar (often meaning "return values that match the
150         * given code but that have no codesystem) this method will return <code>""</code>
151         * </p>
152         */
153        public String getSystem() {
154                return mySystem;
155        }
156
157        /**
158         * Returns the value for the token (generally the value to the right of the
159         * vertical bar on the URL) 
160         */
161        public String getValue() {
162                return myValue;
163        }
164
165        public InternalCodingDt getValueAsCoding() {
166                return new InternalCodingDt(mySystem, myValue);
167        }
168
169        public String getValueNotNull() {
170                return defaultString(myValue);
171        }
172
173        public boolean isEmpty() {
174                return StringUtils.isEmpty(myValue);
175        }
176
177        /**
178         * Returns true if {@link #getModifier()} returns {@link TokenParamModifier#TEXT}
179         */
180        public boolean isText() {
181                return myModifier == TokenParamModifier.TEXT;
182        }
183
184        public TokenParam setModifier(TokenParamModifier theModifier) {
185                myModifier = theModifier;
186                return this;
187        }
188
189        public TokenParam setSystem(String theSystem) {
190                mySystem = theSystem;
191                return this;
192        }
193
194        /**
195         * @deprecated Use {@link #setModifier(TokenParamModifier)} instead
196         */
197        @Deprecated
198        public TokenParam setText(boolean theText) {
199                if (theText) {
200                        myModifier = TokenParamModifier.TEXT;
201                } else {
202                        myModifier = null;
203                }
204                return this;
205        }
206
207        public TokenParam setValue(String theValue) {
208                myValue = theValue;
209                return this;
210        }
211
212        @Override
213        public String toString() {
214                ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
215                builder.append("system", defaultString(getSystem()));
216                if (myModifier != null) {
217                        builder.append(":" + myModifier.getValue());
218                }
219                builder.append("value", getValue());
220                if (getMissing() != null) {
221                        builder.append(":missing", getMissing());
222                }
223                return builder.toString();
224        }
225
226        private static String toSystemValue(UriDt theSystem) {
227                return theSystem.getValueAsString();
228        }
229
230}