001/* 002 * #%L 003 * HAPI FHIR - Core Library 004 * %% 005 * Copyright (C) 2014 - 2024 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.util; 021 022import ca.uhn.fhir.context.BaseRuntimeChildDefinition; 023import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition; 024import ca.uhn.fhir.context.BaseRuntimeElementDefinition; 025import ca.uhn.fhir.context.FhirContext; 026import ca.uhn.fhir.context.RuntimeResourceDefinition; 027import ca.uhn.fhir.i18n.Msg; 028import ca.uhn.fhir.model.api.annotation.Description; 029import ca.uhn.fhir.model.primitive.StringDt; 030import jakarta.annotation.Nullable; 031import org.apache.commons.lang3.Validate; 032import org.hl7.fhir.instance.model.api.IBase; 033import org.hl7.fhir.instance.model.api.IBaseDatatype; 034import org.hl7.fhir.instance.model.api.IBaseParameters; 035import org.hl7.fhir.instance.model.api.IBaseReference; 036import org.hl7.fhir.instance.model.api.IBaseResource; 037import org.hl7.fhir.instance.model.api.IPrimitiveType; 038 039import java.lang.annotation.Annotation; 040import java.lang.reflect.AnnotatedElement; 041import java.math.BigDecimal; 042import java.util.ArrayList; 043import java.util.Arrays; 044import java.util.Collection; 045import java.util.List; 046import java.util.Objects; 047import java.util.Optional; 048import java.util.function.Function; 049import java.util.stream.Collectors; 050 051import static org.apache.commons.lang3.StringUtils.defaultIfBlank; 052import static org.apache.commons.lang3.StringUtils.isBlank; 053 054/** 055 * Utilities for dealing with parameters resources in a version indepenedent way 056 */ 057public class ParametersUtil { 058 059 public static Optional<String> getNamedParameterValueAsString( 060 FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 061 Function<IPrimitiveType<?>, String> mapper = t -> defaultIfBlank(t.getValueAsString(), null); 062 return extractNamedParameterValues(theCtx, theParameters, theParameterName, mapper).stream() 063 .findFirst(); 064 } 065 066 public static List<String> getNamedParameterValuesAsString( 067 FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 068 Function<IPrimitiveType<?>, String> mapper = t -> defaultIfBlank(t.getValueAsString(), null); 069 return extractNamedParameterValues(theCtx, theParameters, theParameterName, mapper); 070 } 071 072 public static List<Integer> getNamedParameterValuesAsInteger( 073 FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 074 Function<IPrimitiveType<?>, Integer> mapper = t -> (Integer) t.getValue(); 075 return extractNamedParameterValues(theCtx, theParameters, theParameterName, mapper); 076 } 077 078 public static Optional<Integer> getNamedParameterValueAsInteger( 079 FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 080 return getNamedParameterValuesAsInteger(theCtx, theParameters, theParameterName).stream() 081 .findFirst(); 082 } 083 084 /** 085 * Returns the resource within a parameter. 086 * @param theCtx thr FHIR context 087 * @param theParameters the parameters instance where to look for the resource 088 * @param theParameterName the parameter name 089 * @return the resource 090 */ 091 public static Optional<IBaseResource> getNamedParameterResource( 092 FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 093 return extractNamedParameterResources(theCtx, theParameters, theParameterName).stream() 094 .findFirst(); 095 } 096 097 public static Optional<IBase> getNamedParameter( 098 FhirContext theCtx, IBaseResource theParameters, String theParameterName) { 099 return getNamedParameters(theCtx, theParameters, theParameterName).stream() 100 .findFirst(); 101 } 102 103 public static List<IBase> getNamedParameters( 104 FhirContext theCtx, IBaseResource theParameters, String theParameterName) { 105 Validate.notNull(theParameters, "theParameters must not be null"); 106 RuntimeResourceDefinition resDef = theCtx.getResourceDefinition(theParameters.getClass()); 107 BaseRuntimeChildDefinition parameterChild = resDef.getChildByName("parameter"); 108 List<IBase> parameterReps = parameterChild.getAccessor().getValues(theParameters); 109 110 return parameterReps.stream() 111 .filter(param -> { 112 BaseRuntimeElementCompositeDefinition<?> nextParameterDef = 113 (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(param.getClass()); 114 BaseRuntimeChildDefinition nameChild = nextParameterDef.getChildByName("name"); 115 List<IBase> nameValues = nameChild.getAccessor().getValues(param); 116 Optional<? extends IPrimitiveType<?>> nameValue = nameValues.stream() 117 .filter(t -> t instanceof IPrimitiveType<?>) 118 .map(t -> ((IPrimitiveType<?>) t)) 119 .findFirst(); 120 return nameValue.isPresent() 121 && theParameterName.equals(nameValue.get().getValueAsString()); 122 }) 123 .collect(Collectors.toList()); 124 } 125 126 public static Optional<IBase> getParameterPart(FhirContext theCtx, IBase theParameter, String theParameterName) { 127 BaseRuntimeElementCompositeDefinition<?> nextParameterDef = 128 (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(theParameter.getClass()); 129 BaseRuntimeChildDefinition valueChild = nextParameterDef.getChildByName("part"); 130 List<IBase> parts = valueChild.getAccessor().getValues(theParameter); 131 132 for (IBase nextPart : parts) { 133 Optional<IPrimitiveType> name = theCtx.newTerser().getSingleValue(nextPart, "name", IPrimitiveType.class); 134 if (name.isPresent() && theParameterName.equals(name.get().getValueAsString())) { 135 return Optional.of(nextPart); 136 } 137 } 138 139 return Optional.empty(); 140 } 141 142 public static Optional<IBase> getParameterPartValue( 143 FhirContext theCtx, IBase theParameter, String theParameterName) { 144 Optional<IBase> part = getParameterPart(theCtx, theParameter, theParameterName); 145 if (part.isPresent()) { 146 return theCtx.newTerser().getSingleValue(part.get(), "value[x]", IBase.class); 147 } else { 148 return Optional.empty(); 149 } 150 } 151 152 public static String getParameterPartValueAsString( 153 FhirContext theCtx, IBase theParameter, String theParameterName) { 154 return getParameterPartValue(theCtx, theParameter, theParameterName) 155 .map(t -> (IPrimitiveType<?>) t) 156 .map(t -> t.getValueAsString()) 157 .orElse(null); 158 } 159 160 public static Optional<Integer> getParameterPartValueAsInteger( 161 FhirContext theCtx, IBase theParameter, String theParameterName) { 162 return getParameterPartValue(theCtx, theParameter, theParameterName) 163 .filter(t -> IPrimitiveType.class.isAssignableFrom(t.getClass())) 164 .map(t -> (IPrimitiveType<?>) t) 165 .map(IPrimitiveType::getValue) 166 .filter(t -> Integer.class.isAssignableFrom(t.getClass())) 167 .map(t -> (Integer) t); 168 } 169 170 private static <T> List<T> extractNamedParameterValues( 171 FhirContext theCtx, 172 IBaseParameters theParameters, 173 String theParameterName, 174 Function<IPrimitiveType<?>, T> theMapper) { 175 List<T> retVal = new ArrayList<>(); 176 177 List<IBase> namedParameters = getNamedParameters(theCtx, theParameters, theParameterName); 178 for (IBase nextParameter : namedParameters) { 179 BaseRuntimeElementCompositeDefinition<?> nextParameterDef = 180 (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(nextParameter.getClass()); 181 BaseRuntimeChildDefinition valueChild = nextParameterDef.getChildByName("value[x]"); 182 List<IBase> valueValues = valueChild.getAccessor().getValues(nextParameter); 183 valueValues.stream() 184 .filter(t -> t instanceof IPrimitiveType<?>) 185 .map(t -> ((IPrimitiveType<?>) t)) 186 .map(theMapper) 187 .filter(Objects::nonNull) 188 .forEach(retVal::add); 189 } 190 return retVal; 191 } 192 193 private static List<IBaseResource> extractNamedParameterResources( 194 FhirContext theCtx, IBaseParameters theParameters, String theParameterName) { 195 List<IBaseResource> retVal = new ArrayList<>(); 196 197 List<IBase> namedParameters = getNamedParameters(theCtx, theParameters, theParameterName); 198 for (IBase nextParameter : namedParameters) { 199 BaseRuntimeElementCompositeDefinition<?> nextParameterDef = 200 (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(nextParameter.getClass()); 201 BaseRuntimeChildDefinition resourceChild = nextParameterDef.getChildByName("resource"); 202 List<IBase> resourceValues = resourceChild.getAccessor().getValues(nextParameter); 203 resourceValues.stream() 204 .filter(IBaseResource.class::isInstance) 205 .map(t -> ((IBaseResource) t)) 206 .forEach(retVal::add); 207 } 208 return retVal; 209 } 210 211 private static void addClientParameter( 212 FhirContext theContext, 213 Object theValue, 214 IBaseResource theTargetResource, 215 BaseRuntimeChildDefinition paramChild, 216 BaseRuntimeElementCompositeDefinition<?> paramChildElem, 217 String theName) { 218 Validate.notNull(theValue, "theValue must not be null"); 219 220 if (theValue instanceof IBaseResource) { 221 IBase parameter = 222 createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName); 223 paramChildElem.getChildByName("resource").getMutator().addValue(parameter, (IBaseResource) theValue); 224 } else if (theValue instanceof IBaseDatatype) { 225 IBase parameter = 226 createParameterRepetition(theContext, theTargetResource, paramChild, paramChildElem, theName); 227 paramChildElem.getChildByName("value[x]").getMutator().addValue(parameter, (IBaseDatatype) theValue); 228 } else if (theValue instanceof Collection) { 229 Collection<?> collection = (Collection<?>) theValue; 230 for (Object next : collection) { 231 addClientParameter(theContext, next, theTargetResource, paramChild, paramChildElem, theName); 232 } 233 } else { 234 throw new IllegalArgumentException(Msg.code(1806) + "Don't know how to handle value of type " 235 + theValue.getClass() + " for parameter " + theName); 236 } 237 } 238 239 /** 240 * Add a parameter value to a Parameters resource 241 * 242 * @param theContext The FhirContext 243 * @param theParameters The Parameters resource 244 * @param theName The parameter name 245 * @param theValue The parameter value (can be a {@link IBaseResource resource} or a {@link IBaseDatatype datatype}) 246 */ 247 public static void addParameterToParameters( 248 FhirContext theContext, IBaseParameters theParameters, String theName, Object theValue) { 249 RuntimeResourceDefinition def = theContext.getResourceDefinition(theParameters); 250 BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter"); 251 BaseRuntimeElementCompositeDefinition<?> paramChildElem = 252 (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter"); 253 254 addClientParameter(theContext, theValue, theParameters, paramChild, paramChildElem, theName); 255 } 256 257 /** 258 * Add a parameter value to a Parameters resource 259 * 260 * @param theContext The FhirContext 261 * @param theParameters The Parameters resource 262 * @param theName The parameter name 263 * @param thePrimitiveDatatype The datatype, e.g. "string", or "uri" 264 * @param theValue The value 265 */ 266 public static void addParameterToParameters( 267 FhirContext theContext, 268 IBaseParameters theParameters, 269 String theName, 270 String thePrimitiveDatatype, 271 String theValue) { 272 Validate.notBlank(thePrimitiveDatatype, "thePrimitiveDatatype must not be null or empty"); 273 274 BaseRuntimeElementDefinition<?> datatypeDef = theContext.getElementDefinition(thePrimitiveDatatype); 275 IPrimitiveType<?> value = (IPrimitiveType<?>) datatypeDef.newInstance(); 276 value.setValueAsString(theValue); 277 278 addParameterToParameters(theContext, theParameters, theName, value); 279 } 280 281 private static IBase createParameterRepetition( 282 FhirContext theContext, 283 IBase theTargetResource, 284 BaseRuntimeChildDefinition paramChild, 285 BaseRuntimeElementCompositeDefinition<?> paramChildElem, 286 String theName) { 287 IBase parameter = paramChildElem.newInstance(); 288 paramChild.getMutator().addValue(theTargetResource, parameter); 289 IPrimitiveType<?> value; 290 value = createString(theContext, theName); 291 paramChildElem.getChildByName("name").getMutator().addValue(parameter, value); 292 return parameter; 293 } 294 295 public static IPrimitiveType<?> createString(FhirContext theContext, String theValue) { 296 IPrimitiveType<?> value; 297 if (theContext.getVersion().getVersion().isRi()) { 298 value = (IPrimitiveType<?>) 299 theContext.getElementDefinition("string").newInstance(theValue); 300 } else { 301 value = new StringDt(theValue); 302 } 303 return value; 304 } 305 306 public static IPrimitiveType<?> createUri(FhirContext theContext, String theValue) { 307 IPrimitiveType<?> value = 308 (IPrimitiveType<?>) theContext.getElementDefinition("uri").newInstance(theValue); 309 return value; 310 } 311 312 public static IPrimitiveType<?> createCode(FhirContext theContext, String theValue) { 313 IPrimitiveType<?> value = 314 (IPrimitiveType<?>) theContext.getElementDefinition("code").newInstance(theValue); 315 return value; 316 } 317 318 public static IBaseParameters newInstance(FhirContext theContext) { 319 Validate.notNull(theContext, "theContext must not be null"); 320 return (IBaseParameters) theContext.getResourceDefinition("Parameters").newInstance(); 321 } 322 323 @SuppressWarnings("unchecked") 324 public static void addParameterToParametersBoolean( 325 FhirContext theCtx, IBaseParameters theParameters, String theName, boolean theValue) { 326 addParameterToParameters(theCtx, theParameters, theName, theCtx.getPrimitiveBoolean(theValue)); 327 } 328 329 @SuppressWarnings("unchecked") 330 public static void addParameterToParametersCode( 331 FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) { 332 IPrimitiveType<String> value = 333 (IPrimitiveType<String>) theCtx.getElementDefinition("code").newInstance(); 334 value.setValue(theValue); 335 addParameterToParameters(theCtx, theParameters, theName, value); 336 } 337 338 @SuppressWarnings("unchecked") 339 public static void addParameterToParametersInteger( 340 FhirContext theCtx, IBaseParameters theParameters, String theName, int theValue) { 341 IPrimitiveType<Integer> count = 342 (IPrimitiveType<Integer>) theCtx.getElementDefinition("integer").newInstance(); 343 count.setValue(theValue); 344 addParameterToParameters(theCtx, theParameters, theName, count); 345 } 346 347 public static void addParameterToParametersLong( 348 FhirContext theCtx, IBaseParameters theParameters, String theName, long theValue) { 349 addParameterToParametersDecimal(theCtx, theParameters, theName, BigDecimal.valueOf(theValue)); 350 } 351 352 public static void addParameterToParametersDecimal( 353 FhirContext theCtx, IBaseParameters theParameters, String theName, BigDecimal theValue) { 354 IPrimitiveType<BigDecimal> count = (IPrimitiveType<BigDecimal>) 355 theCtx.getElementDefinition("decimal").newInstance(); 356 count.setValue(theValue); 357 addParameterToParameters(theCtx, theParameters, theName, count); 358 } 359 360 public static void addParameterToParametersReference( 361 FhirContext theCtx, IBaseParameters theParameters, String theName, String theReference) { 362 IBaseReference target = 363 (IBaseReference) theCtx.getElementDefinition("reference").newInstance(); 364 target.setReference(theReference); 365 addParameterToParameters(theCtx, theParameters, theName, target); 366 } 367 368 @SuppressWarnings("unchecked") 369 public static void addParameterToParametersString( 370 FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) { 371 IPrimitiveType<String> value = 372 (IPrimitiveType<String>) theCtx.getElementDefinition("string").newInstance(); 373 value.setValue(theValue); 374 addParameterToParameters(theCtx, theParameters, theName, value); 375 } 376 377 @SuppressWarnings("unchecked") 378 public static void addParameterToParametersUri( 379 FhirContext theCtx, IBaseParameters theParameters, String theName, String theValue) { 380 IPrimitiveType<String> value = 381 (IPrimitiveType<String>) theCtx.getElementDefinition("uri").newInstance(); 382 value.setValue(theValue); 383 addParameterToParameters(theCtx, theParameters, theName, value); 384 } 385 386 /** 387 * Add a parameter with no value (typically because we'll be adding sub-parameters) 388 */ 389 public static IBase addParameterToParameters( 390 FhirContext theContext, IBaseParameters theParameters, String theName) { 391 RuntimeResourceDefinition def = theContext.getResourceDefinition(theParameters); 392 BaseRuntimeChildDefinition paramChild = def.getChildByName("parameter"); 393 BaseRuntimeElementCompositeDefinition<?> paramChildElem = 394 (BaseRuntimeElementCompositeDefinition<?>) paramChild.getChildByName("parameter"); 395 396 return createParameterRepetition(theContext, theParameters, paramChild, paramChildElem, theName); 397 } 398 399 public static void addPartCode(FhirContext theContext, IBase theParameter, String theName, String theCode) { 400 IPrimitiveType<String> value = 401 (IPrimitiveType<String>) theContext.getElementDefinition("code").newInstance(); 402 value.setValue(theCode); 403 404 addPart(theContext, theParameter, theName, value); 405 } 406 407 public static void addPartInteger(FhirContext theContext, IBase theParameter, String theName, Integer theInteger) { 408 IPrimitiveType<Integer> value = (IPrimitiveType<Integer>) 409 theContext.getElementDefinition("integer").newInstance(); 410 value.setValue(theInteger); 411 412 addPart(theContext, theParameter, theName, value); 413 } 414 415 public static void addPartString(FhirContext theContext, IBase theParameter, String theName, String theValue) { 416 IPrimitiveType<String> value = (IPrimitiveType<String>) 417 theContext.getElementDefinition("string").newInstance(); 418 value.setValue(theValue); 419 420 addPart(theContext, theParameter, theName, value); 421 } 422 423 public static void addPartUrl(FhirContext theContext, IBase theParameter, String theName, String theCode) { 424 IPrimitiveType<String> value = 425 (IPrimitiveType<String>) theContext.getElementDefinition("url").newInstance(); 426 value.setValue(theCode); 427 428 addPart(theContext, theParameter, theName, value); 429 } 430 431 public static void addPartBoolean(FhirContext theContext, IBase theParameter, String theName, Boolean theValue) { 432 addPart(theContext, theParameter, theName, theContext.getPrimitiveBoolean(theValue)); 433 } 434 435 public static void addPartDecimal(FhirContext theContext, IBase theParameter, String theName, Double theValue) { 436 IPrimitiveType<BigDecimal> value = (IPrimitiveType<BigDecimal>) 437 theContext.getElementDefinition("decimal").newInstance(); 438 if (theValue == null) { 439 value.setValue(null); 440 } else { 441 BigDecimal decimalValue = BigDecimal.valueOf(theValue); 442 if (decimalValue.scale() < 0) { 443 decimalValue = decimalValue.setScale(0); 444 } 445 value.setValue(decimalValue); 446 } 447 addPart(theContext, theParameter, theName, value); 448 } 449 450 public static void addPartCoding( 451 FhirContext theContext, 452 IBase theParameter, 453 String theName, 454 String theSystem, 455 String theCode, 456 String theDisplay) { 457 IBase coding = theContext.getElementDefinition("coding").newInstance(); 458 459 BaseRuntimeElementCompositeDefinition<?> codingDef = 460 (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(coding.getClass()); 461 codingDef.getChildByName("system").getMutator().addValue(coding, createUri(theContext, theSystem)); 462 codingDef.getChildByName("code").getMutator().addValue(coding, createCode(theContext, theCode)); 463 codingDef.getChildByName("display").getMutator().addValue(coding, createString(theContext, theDisplay)); 464 465 addPart(theContext, theParameter, theName, coding); 466 } 467 468 public static IBase addPart(FhirContext theContext, IBase theParameter, String theName, @Nullable IBase theValue) { 469 BaseRuntimeElementCompositeDefinition<?> def = 470 (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theParameter.getClass()); 471 BaseRuntimeChildDefinition partChild = def.getChildByName("part"); 472 473 BaseRuntimeElementCompositeDefinition<?> partChildElem = 474 (BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part"); 475 IBase part = partChildElem.newInstance(); 476 partChild.getMutator().addValue(theParameter, part); 477 478 IPrimitiveType<String> name = (IPrimitiveType<String>) 479 theContext.getElementDefinition("string").newInstance(); 480 name.setValue(theName); 481 partChildElem.getChildByName("name").getMutator().addValue(part, name); 482 483 if (theValue != null) { 484 if (theValue instanceof IBaseResource) { 485 partChildElem.getChildByName("resource").getMutator().addValue(part, theValue); 486 } else { 487 partChildElem.getChildByName("value[x]").getMutator().addValue(part, theValue); 488 } 489 } 490 return part; 491 } 492 493 public static IBase createPart(FhirContext theContext, IBase thePart, String theName) { 494 BaseRuntimeElementCompositeDefinition<?> def = 495 (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(thePart.getClass()); 496 BaseRuntimeChildDefinition partChild = def.getChildByName("part"); 497 498 BaseRuntimeElementCompositeDefinition<?> partChildElem = 499 (BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part"); 500 501 return createParameterRepetition(theContext, thePart, partChild, partChildElem, theName); 502 } 503 504 public static void addPartResource( 505 FhirContext theContext, IBase theParameter, String theName, IBaseResource theValue) { 506 BaseRuntimeElementCompositeDefinition<?> def = 507 (BaseRuntimeElementCompositeDefinition<?>) theContext.getElementDefinition(theParameter.getClass()); 508 BaseRuntimeChildDefinition partChild = def.getChildByName("part"); 509 510 BaseRuntimeElementCompositeDefinition<?> partChildElem = 511 (BaseRuntimeElementCompositeDefinition<?>) partChild.getChildByName("part"); 512 IBase part = partChildElem.newInstance(); 513 partChild.getMutator().addValue(theParameter, part); 514 515 IPrimitiveType<String> name = (IPrimitiveType<String>) 516 theContext.getElementDefinition("string").newInstance(); 517 name.setValue(theName); 518 partChildElem.getChildByName("name").getMutator().addValue(part, name); 519 520 partChildElem.getChildByName("resource").getMutator().addValue(part, theValue); 521 } 522 523 public static List<String> getNamedParameterPartAsString( 524 FhirContext theCtx, IBaseParameters theParameters, String thePartName, String theParameterName) { 525 return extractNamedParameterPartsAsString(theCtx, theParameters, thePartName, theParameterName); 526 } 527 528 // TODO KHS need to consolidate duplicated functionality that came in from different branches 529 private static List<String> extractNamedParameterPartsAsString( 530 FhirContext theCtx, IBaseParameters theParameters, String thePartName, String theParameterName) { 531 List<IBase> parameterReps = getParameterReps(theCtx, theParameters); 532 533 List<String> retVal = new ArrayList<>(); 534 535 for (IBase nextParameter : parameterReps) { 536 BaseRuntimeElementCompositeDefinition<?> nextParameterDef = 537 (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(nextParameter.getClass()); 538 Optional<? extends IPrimitiveType<?>> nameValue = getNameValue(nextParameter, nextParameterDef); 539 if (!nameValue.isPresent() || !thePartName.equals(nameValue.get().getValueAsString())) { 540 continue; 541 } 542 543 BaseRuntimeChildDefinition partChild = nextParameterDef.getChildByName("part"); 544 List<IBase> partValues = partChild.getAccessor().getValues(nextParameter); 545 for (IBase partValue : partValues) { 546 BaseRuntimeElementCompositeDefinition<?> partParameterDef = 547 (BaseRuntimeElementCompositeDefinition<?>) theCtx.getElementDefinition(partValue.getClass()); 548 Optional<? extends IPrimitiveType<?>> partNameValue = getNameValue(partValue, partParameterDef); 549 if (!partNameValue.isPresent() 550 || !theParameterName.equals(partNameValue.get().getValueAsString())) { 551 continue; 552 } 553 BaseRuntimeChildDefinition valueChild = partParameterDef.getChildByName("value[x]"); 554 List<IBase> valueValues = valueChild.getAccessor().getValues(partValue); 555 valueValues.stream() 556 .filter(t -> t instanceof IPrimitiveType<?>) 557 .map(t -> ((IPrimitiveType<String>) t)) 558 .map(t -> defaultIfBlank(t.getValueAsString(), null)) 559 .filter(t -> t != null) 560 .forEach(retVal::add); 561 } 562 } 563 return retVal; 564 } 565 566 private static List<IBase> getParameterReps(FhirContext theCtx, IBaseParameters theParameters) { 567 Validate.notNull(theParameters, "theParameters must not be null"); 568 RuntimeResourceDefinition resDef = theCtx.getResourceDefinition(theParameters.getClass()); 569 BaseRuntimeChildDefinition parameterChild = resDef.getChildByName("parameter"); 570 return parameterChild.getAccessor().getValues(theParameters); 571 } 572 573 private static Optional<? extends IPrimitiveType<?>> getNameValue( 574 IBase nextParameter, BaseRuntimeElementCompositeDefinition<?> theNextParameterDef) { 575 BaseRuntimeChildDefinition nameChild = theNextParameterDef.getChildByName("name"); 576 List<IBase> nameValues = nameChild.getAccessor().getValues(nextParameter); 577 return nameValues.stream() 578 .filter(t -> t instanceof IPrimitiveType<?>) 579 .map(t -> ((IPrimitiveType<?>) t)) 580 .findFirst(); 581 } 582 583 @Nullable 584 public static String extractDescription(AnnotatedElement theType) { 585 Description description = theType.getAnnotation(Description.class); 586 if (description != null) { 587 return extractDescription(description); 588 } else { 589 return null; 590 } 591 } 592 593 @Nullable 594 public static String extractDescription(Description desc) { 595 String description = desc.value(); 596 if (isBlank(description)) { 597 description = desc.formalDefinition(); 598 } 599 if (isBlank(description)) { 600 description = desc.shortDefinition(); 601 } 602 return defaultIfBlank(description, null); 603 } 604 605 @Nullable 606 public static String extractShortDefinition(AnnotatedElement theType) { 607 Description description = theType.getAnnotation(Description.class); 608 if (description != null) { 609 return defaultIfBlank(description.shortDefinition(), null); 610 } else { 611 return null; 612 } 613 } 614 615 public static String extractDescription(Annotation[] theParameterAnnotations) { 616 for (Annotation next : theParameterAnnotations) { 617 if (next instanceof Description) { 618 return extractDescription((Description) next); 619 } 620 } 621 return null; 622 } 623 624 public static List<String> extractExamples(Annotation[] theParameterAnnotations) { 625 ArrayList<String> retVal = null; 626 for (Annotation next : theParameterAnnotations) { 627 if (next instanceof Description) { 628 String[] examples = ((Description) next).example(); 629 if (examples.length > 0) { 630 if (retVal == null) { 631 retVal = new ArrayList<>(); 632 } 633 retVal.addAll(Arrays.asList(examples)); 634 } 635 } 636 } 637 return retVal; 638 } 639}