001package ca.uhn.fhir.rest.param; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2019 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 ca.uhn.fhir.model.primitive.IdDt.isValidLong; 023import static org.apache.commons.lang3.StringUtils.isBlank; 024import static org.apache.commons.lang3.StringUtils.isNotBlank; 025 026import java.math.BigDecimal; 027 028import org.apache.commons.lang3.builder.ToStringBuilder; 029import org.apache.commons.lang3.builder.ToStringStyle; 030import org.hl7.fhir.instance.model.api.IBaseResource; 031 032import ca.uhn.fhir.context.FhirContext; 033import ca.uhn.fhir.model.primitive.IdDt; 034import ca.uhn.fhir.util.CoverageIgnore; 035 036public class ReferenceParam extends BaseParam /*implements IQueryParameterType*/ { 037 038 private String myChain; 039 040 private final IdDt myId = new IdDt(); 041 /** 042 * Constructor 043 */ 044 public ReferenceParam() { 045 super(); 046 } 047 048 /** 049 * Constructor 050 */ 051 public ReferenceParam(String theValue) { 052 setValueAsQueryToken(null, null, null, theValue); 053 } 054 055 /** 056 * Constructor 057 */ 058 public ReferenceParam(String theChain, String theValue) { 059 setValueAsQueryToken(null, null, null, theValue); 060 setChain(theChain); 061 } 062 063 /** 064 * Constructor 065 */ 066 public ReferenceParam(String theResourceType, String theChain, String theValue) { 067 if (isNotBlank(theResourceType)) { 068 setValue(theResourceType + "/" + theValue); 069 } else { 070 setValue(theValue); 071 } 072 setChain(theChain); 073 } 074 075 @Override 076 String doGetQueryParameterQualifier() { 077 StringBuilder b = new StringBuilder(); 078 if (isNotBlank(myChain)) { 079 if (isNotBlank(getResourceType())) { 080 b.append(':'); 081 b.append(getResourceType()); 082 } 083 b.append('.'); 084 b.append(myChain); 085 } 086 if (b.length() != 0) { 087 return b.toString(); 088 } 089 return null; 090 } 091 092 @Override 093 String doGetValueAsQueryToken(FhirContext theContext) { 094 if (isBlank(myId.getResourceType())) { 095 return myId.getValue(); // e.g. urn:asdjd or 123 or cid:wieiuru or #1 096 } else { 097 if (isBlank(getChain())) { 098 return getResourceType() + "/" + myId.getIdPart(); 099 } 100 return myId.getIdPart(); 101 } 102 } 103 104 @Override 105 void doSetValueAsQueryToken(FhirContext theContext, String theParamName, String theQualifier, String theValue) { 106 String q = theQualifier; 107 String resourceType = null; 108 boolean skipSetValue = false; 109 if (isNotBlank(q)) { 110 if (q.startsWith(":")) { 111 int nextIdx = q.indexOf('.'); 112 if (nextIdx != -1) { 113 resourceType = q.substring(1, nextIdx); 114 myChain = q.substring(nextIdx + 1); 115 // type is explicitly defined so use it 116 myId.setParts(null, resourceType, theValue, null); 117 skipSetValue = true; 118 } else { 119 resourceType = q.substring(1); 120 } 121 } else if (q.startsWith(".")) { 122 myChain = q.substring(1); 123 // type not defined but this is a chain, so treat value as opaque 124 myId.setParts(null, null, theValue, null); 125 skipSetValue = true; 126 } 127 } 128 129 if (!skipSetValue) { 130 setValue(theValue); 131 132 if (isNotBlank(resourceType) && isBlank(getResourceType())) { 133 setValue(resourceType + '/' + theValue); 134 } 135 } 136 } 137 138 139 140 @CoverageIgnore 141 public String getBaseUrl() { 142 return myId.getBaseUrl(); 143 } 144 145 146 public String getChain() { 147 return myChain; 148 } 149 150 151 @CoverageIgnore 152 public String getIdPart() { 153 return myId.getIdPart(); 154 } 155 156 @CoverageIgnore 157 public BigDecimal getIdPartAsBigDecimal() { 158 return myId.getIdPartAsBigDecimal(); 159 } 160 161 @CoverageIgnore 162 public Long getIdPartAsLong() { 163 return myId.getIdPartAsLong(); 164 } 165 166 public String getResourceType() { 167 return myId.getResourceType(); 168 } 169 170 public Class<? extends IBaseResource> getResourceType(FhirContext theCtx) { 171 if (isBlank(getResourceType())) { 172 return null; 173 } 174 return theCtx.getResourceDefinition(getResourceType()).getImplementingClass(); 175 } 176 177 public String getValue() { 178 return myId.getValue(); 179 } 180 181 public boolean hasResourceType() { 182 return myId.hasResourceType(); 183 } 184 185 @Override 186 protected boolean isSupportsChain() { 187 return true; 188 } 189 190 public ReferenceParam setChain(String theChain) { 191 myChain = theChain; 192 return this; 193 } 194 195 public ReferenceParam setValue(String theValue) { 196 myId.setValue(theValue); 197 return this; 198 } 199 200 /** 201 * Returns a new param containing the same value as this param, but with the type copnverted 202 * to {@link DateParam}. This is useful if you are using reference parameters and want to handle 203 * chained parameters of different types in a single method. 204 * <p> 205 * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a> 206 * in the HAPI FHIR documentation for an example of how to use this method. 207 * </p> 208 */ 209 public DateParam toDateParam(FhirContext theContext) { 210 DateParam retVal = new DateParam(); 211 retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext)); 212 return retVal; 213 } 214 215 /** 216 * Returns a new param containing the same value as this param, but with the type copnverted 217 * to {@link NumberParam}. This is useful if you are using reference parameters and want to handle 218 * chained parameters of different types in a single method. 219 * <p> 220 * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a> 221 * in the HAPI FHIR documentation for an example of how to use this method. 222 * </p> 223 */ 224 public NumberParam toNumberParam(FhirContext theContext) { 225 NumberParam retVal = new NumberParam(); 226 retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext)); 227 return retVal; 228 } 229 230 /** 231 * Returns a new param containing the same value as this param, but with the type copnverted 232 * to {@link QuantityParam}. This is useful if you are using reference parameters and want to handle 233 * chained parameters of different types in a single method. 234 * <p> 235 * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a> 236 * in the HAPI FHIR documentation for an example of how to use this method. 237 * </p> 238 */ 239 public QuantityParam toQuantityParam(FhirContext theContext) { 240 QuantityParam retVal = new QuantityParam(); 241 retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext)); 242 return retVal; 243 } 244 245 @Override 246 public String toString() { 247 ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE); 248 if (isNotBlank(myChain)) { 249 b.append("chain", myChain); 250 } 251 b.append("value", getValue()); 252 return b.build(); 253 } 254 255 /** 256 * Returns a new param containing the same value as this param, but with the type copnverted 257 * to {@link StringParam}. This is useful if you are using reference parameters and want to handle 258 * chained parameters of different types in a single method. 259 * <p> 260 * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a> 261 * in the HAPI FHIR documentation for an example of how to use this method. 262 * </p> 263 */ 264 public StringParam toStringParam(FhirContext theContext) { 265 StringParam retVal = new StringParam(); 266 retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext)); 267 return retVal; 268 } 269 270 /** 271 * Returns a new param containing the same value as this param, but with the type copnverted 272 * to {@link TokenParam}. This is useful if you are using reference parameters and want to handle 273 * chained parameters of different types in a single method. 274 * <p> 275 * See <a href="http://jamesagnew.github.io/hapi-fhir/doc_rest_operations.html#dynamic_chains">Dynamic Chains</a> 276 * in the HAPI FHIR documentation for an example of how to use this method. 277 * </p> 278 */ 279 public TokenParam toTokenParam(FhirContext theContext) { 280 TokenParam retVal = new TokenParam(); 281 retVal.setValueAsQueryToken(theContext, null, null, getValueAsQueryToken(theContext)); 282 return retVal; 283 } 284 285 public boolean isIdPartValidLong() { 286 return isValidLong(getIdPart()); 287 } 288}