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