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