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