001/*
002 * #%L
003 * HAPI FHIR - Core Library
004 * %%
005 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.rest.param;
021
022import ca.uhn.fhir.context.FhirContext;
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.model.api.IQueryParameterType;
025import ca.uhn.fhir.model.primitive.StringDt;
026import ca.uhn.fhir.rest.api.Constants;
027import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
028import org.apache.commons.lang3.StringUtils;
029import org.apache.commons.lang3.builder.EqualsBuilder;
030import org.apache.commons.lang3.builder.HashCodeBuilder;
031import org.apache.commons.lang3.builder.ToStringBuilder;
032import org.apache.commons.lang3.builder.ToStringStyle;
033import org.slf4j.Logger;
034import org.slf4j.LoggerFactory;
035
036import static org.apache.commons.lang3.StringUtils.defaultString;
037
038public class StringParam extends BaseParam implements IQueryParameterType {
039
040        private static final Logger ourLog = LoggerFactory.getLogger(StringParam.class);
041
042        private boolean myText;
043        private boolean myContains;
044        private boolean myExact;
045        private String myValue;
046
047        private Boolean myNicknameExpand;
048
049
050        /**
051         * Constructor
052         */
053        public StringParam() {
054        }
055
056        /**
057         * Constructor
058         */
059        public StringParam(String theValue) {
060                setValue(theValue);
061        }
062
063        /**
064         * Constructor
065         */
066        public StringParam(String theValue, boolean theExact) {
067                setValue(theValue);
068                setExact(theExact);
069        }
070
071        @Override
072        String doGetQueryParameterQualifier() {
073                if (isExact()) {
074                        return Constants.PARAMQUALIFIER_STRING_EXACT;
075                } else if (isContains()) {
076                        return Constants.PARAMQUALIFIER_STRING_CONTAINS;
077                } else if (isText()) {
078                        return Constants.PARAMQUALIFIER_STRING_TEXT;
079                } else {
080                        return null;
081                }
082        }
083
084        @Override
085        String doGetValueAsQueryToken(FhirContext theContext) {
086                return ParameterUtil.escape(myValue);
087        }
088
089        public boolean isNicknameExpand() {
090                return myNicknameExpand != null && myNicknameExpand;
091        }
092
093        public StringParam setNicknameExpand(boolean theNicknameExpand) {
094                myNicknameExpand = theNicknameExpand;
095                return this;
096        }
097
098        @Override
099        public int hashCode() {
100                return new HashCodeBuilder(17, 37)
101                        .append(myExact)
102                        .append(myText)
103                        .append(myContains)
104                        .append(myValue)
105                        .append(getMissing())
106                        .toHashCode();
107        }
108
109        @Override
110        void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) {
111                if (Constants.PARAMQUALIFIER_NICKNAME.equals(theQualifier)) {
112                        myNicknameExpand = true;
113                        theQualifier = "";
114
115                        if (!("name".equals(theParamName) || "given".equals(theParamName))){
116                                ourLog.debug(":nickname qualifier was assigned to a search parameter other than one of the intended parameters \"name\" and \"given\"");
117                        }
118                }
119
120                if (Constants.PARAMQUALIFIER_STRING_EXACT.equals(theQualifier)) {
121                        setExact(true);
122                } else {
123                        setExact(false);
124                }
125                if (Constants.PARAMQUALIFIER_STRING_CONTAINS.equals(theQualifier)) {
126                        setContains(true);
127                } else {
128                        setContains(false);
129                }
130
131                setText( Constants.PARAMQUALIFIER_STRING_TEXT.equals(theQualifier) );
132
133                myValue = ParameterUtil.unescape(theValue);
134        }
135
136        @Override
137        public boolean equals(Object obj) {
138                if (this == obj) {
139                        return true;
140                }
141                if (obj == null) {
142                        return false;
143                }
144                if (!(obj instanceof StringParam)) {
145                        return false;
146                }
147
148                StringParam other = (StringParam) obj;
149
150                EqualsBuilder eb = new EqualsBuilder();
151                eb.append(myExact, other.myExact);
152                eb.append(myText, other.myText);
153                eb.append(myContains, other.myContains);
154                eb.append(myValue, other.myValue);
155                eb.append(getMissing(), other.getMissing());
156
157                return eb.isEquals();
158        }
159
160        public String getValue() {
161                return myValue;
162        }
163
164        public StringParam setValue(String theValue) {
165                myValue = theValue;
166                return this;
167        }
168
169        public StringDt getValueAsStringDt() {
170                return new StringDt(myValue);
171        }
172
173        public String getValueNotNull() {
174                return defaultString(myValue);
175        }
176
177        public boolean isText() { return myText; }
178
179        public void setText(boolean theText) {
180                myText = theText;
181                if (myText) {
182                        setContains(false);
183                        setExact(false);
184                        setMissing(null);
185
186                }
187        }
188
189        /**
190         * String parameter modifier <code>:contains</code>
191         */
192        public boolean isContains() {
193                return myContains;
194        }
195
196        /**
197         * String parameter modifier <code>:contains</code>
198         */
199        public StringParam setContains(boolean theContains) {
200                myContains = theContains;
201                if (myContains) {
202                        setText(false);
203                        setExact(false);
204                        setMissing(null);
205                }
206                return this;
207        }
208
209        public boolean isEmpty() {
210                return StringUtils.isEmpty(myValue);
211        }
212
213        public boolean isExact() {
214                return myExact;
215        }
216
217        public StringParam setExact(boolean theExact) {
218                myExact = theExact;
219                if (myExact) {
220                        setText(false);
221                        setContains(false);
222                        setMissing(null);
223                }
224                return this;
225        }
226
227        @Override
228        public String toString() {
229                ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
230                builder.append("value", getValue());
231                if (myText) {
232                        builder.append("text", myText);
233                }
234                if (myExact) {
235                        builder.append("exact", myExact);
236                }
237                if (myContains) {
238                        builder.append("contains", myContains);
239                }
240                if (getMissing() != null) {
241                        builder.append("missing", getMissing().booleanValue());
242                }
243                return builder.toString();
244        }
245
246}