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