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