001package org.hl7.fhir.common.hapi.validation.validator; 002 003import ca.uhn.fhir.context.FhirVersionEnum; 004import ca.uhn.fhir.context.support.ConceptValidationOptions; 005import ca.uhn.fhir.context.support.IValidationSupport; 006import ca.uhn.fhir.context.support.ValidationSupportContext; 007import ca.uhn.fhir.i18n.Msg; 008import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; 009import ca.uhn.fhir.sl.cache.CacheFactory; 010import ca.uhn.fhir.sl.cache.LoadingCache; 011import ca.uhn.fhir.system.HapiSystemProperties; 012import ca.uhn.hapi.converters.canonical.VersionCanonicalizer; 013import jakarta.annotation.Nonnull; 014import jakarta.annotation.Nullable; 015import org.apache.commons.lang3.Validate; 016import org.apache.commons.lang3.builder.EqualsBuilder; 017import org.apache.commons.lang3.builder.HashCodeBuilder; 018import org.fhir.ucum.UcumService; 019import org.hl7.fhir.exceptions.FHIRException; 020import org.hl7.fhir.exceptions.TerminologyServiceException; 021import org.hl7.fhir.instance.model.api.IBaseResource; 022import org.hl7.fhir.r5.context.IWorkerContext; 023import org.hl7.fhir.r5.context.IWorkerContextManager; 024import org.hl7.fhir.r5.model.CodeSystem; 025import org.hl7.fhir.r5.model.Coding; 026import org.hl7.fhir.r5.model.NamingSystem; 027import org.hl7.fhir.r5.model.PackageInformation; 028import org.hl7.fhir.r5.model.Resource; 029import org.hl7.fhir.r5.model.StructureDefinition; 030import org.hl7.fhir.r5.model.ValueSet; 031import org.hl7.fhir.r5.profilemodel.PEBuilder; 032import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; 033import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass; 034import org.hl7.fhir.r5.utils.validation.IResourceValidator; 035import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier; 036import org.hl7.fhir.utilities.TimeTracker; 037import org.hl7.fhir.utilities.TranslationServices; 038import org.hl7.fhir.utilities.i18n.I18nBase; 039import org.hl7.fhir.utilities.npm.BasePackageCacheManager; 040import org.hl7.fhir.utilities.npm.NpmPackage; 041import org.hl7.fhir.utilities.validation.ValidationMessage; 042import org.hl7.fhir.utilities.validation.ValidationOptions; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045 046import java.io.FileNotFoundException; 047import java.io.IOException; 048import java.util.ArrayList; 049import java.util.List; 050import java.util.Locale; 051import java.util.Map; 052import java.util.Set; 053 054import static org.apache.commons.lang3.StringUtils.isBlank; 055import static org.apache.commons.lang3.StringUtils.isNotBlank; 056 057public class VersionSpecificWorkerContextWrapper extends I18nBase implements IWorkerContext { 058 private static final Logger ourLog = LoggerFactory.getLogger(VersionSpecificWorkerContextWrapper.class); 059 private final ValidationSupportContext myValidationSupportContext; 060 private final VersionCanonicalizer myVersionCanonicalizer; 061 private final LoadingCache<ResourceKey, IBaseResource> myFetchResourceCache; 062 private volatile List<StructureDefinition> myAllStructures; 063 private org.hl7.fhir.r5.model.Parameters myExpansionProfile; 064 065 public VersionSpecificWorkerContextWrapper( 066 ValidationSupportContext theValidationSupportContext, VersionCanonicalizer theVersionCanonicalizer) { 067 myValidationSupportContext = theValidationSupportContext; 068 myVersionCanonicalizer = theVersionCanonicalizer; 069 070 long timeoutMillis = HapiSystemProperties.getTestValidationResourceCachesMs(); 071 072 myFetchResourceCache = CacheFactory.build(timeoutMillis, 10000, key -> { 073 String fetchResourceName = key.getResourceName(); 074 if (myValidationSupportContext 075 .getRootValidationSupport() 076 .getFhirContext() 077 .getVersion() 078 .getVersion() 079 == FhirVersionEnum.DSTU2) { 080 if ("CodeSystem".equals(fetchResourceName)) { 081 fetchResourceName = "ValueSet"; 082 } 083 } 084 085 Class<? extends IBaseResource> fetchResourceType; 086 if (fetchResourceName.equals("Resource")) { 087 fetchResourceType = null; 088 } else { 089 fetchResourceType = myValidationSupportContext 090 .getRootValidationSupport() 091 .getFhirContext() 092 .getResourceDefinition(fetchResourceName) 093 .getImplementingClass(); 094 } 095 096 IBaseResource fetched = myValidationSupportContext 097 .getRootValidationSupport() 098 .fetchResource(fetchResourceType, key.getUri()); 099 100 Resource canonical = myVersionCanonicalizer.resourceToValidatorCanonical(fetched); 101 102 if (canonical instanceof StructureDefinition) { 103 StructureDefinition canonicalSd = (StructureDefinition) canonical; 104 if (canonicalSd.getSnapshot().isEmpty()) { 105 ourLog.info("Generating snapshot for StructureDefinition: {}", canonicalSd.getUrl()); 106 fetched = myValidationSupportContext 107 .getRootValidationSupport() 108 .generateSnapshot(theValidationSupportContext, fetched, "", null, ""); 109 Validate.isTrue( 110 fetched != null, 111 "StructureDefinition %s has no snapshot, and no snapshot generator is configured", 112 key.getUri()); 113 canonical = myVersionCanonicalizer.resourceToValidatorCanonical(fetched); 114 } 115 } 116 117 return canonical; 118 }); 119 120 setValidationMessageLanguage(getLocale()); 121 } 122 123 @Override 124 public Set<String> getBinaryKeysAsSet() { 125 throw new UnsupportedOperationException(Msg.code(2118)); 126 } 127 128 @Override 129 public boolean hasBinaryKey(String s) { 130 return myValidationSupportContext.getRootValidationSupport().fetchBinary(s) != null; 131 } 132 133 @Override 134 public byte[] getBinaryForKey(String s) { 135 return myValidationSupportContext.getRootValidationSupport().fetchBinary(s); 136 } 137 138 @Override 139 public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FHIRException { 140 throw new UnsupportedOperationException(Msg.code(652)); 141 } 142 143 @Override 144 public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader, List<String> types) 145 throws FileNotFoundException, IOException, FHIRException { 146 throw new UnsupportedOperationException(Msg.code(653)); 147 } 148 149 @Override 150 public int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) 151 throws FHIRException { 152 throw new UnsupportedOperationException(Msg.code(654)); 153 } 154 155 @Override 156 public boolean hasPackage(String id, String ver) { 157 throw new UnsupportedOperationException(Msg.code(655)); 158 } 159 160 @Override 161 public boolean hasPackage(PackageInformation packageInformation) { 162 return false; 163 } 164 165 @Override 166 public PackageInformation getPackage(String id, String ver) { 167 return null; 168 } 169 170 @Override 171 public int getClientRetryCount() { 172 throw new UnsupportedOperationException(Msg.code(656)); 173 } 174 175 @Override 176 public IWorkerContext setClientRetryCount(int value) { 177 throw new UnsupportedOperationException(Msg.code(657)); 178 } 179 180 @Override 181 public TimeTracker clock() { 182 return null; 183 } 184 185 @Override 186 public IWorkerContextManager.IPackageLoadingTracker getPackageTracker() { 187 throw new UnsupportedOperationException(Msg.code(2235)); 188 } 189 190 @Override 191 public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker) { 192 throw new UnsupportedOperationException(Msg.code(2266)); 193 } 194 195 @Override 196 public String getSpecUrl() { 197 return ""; 198 } 199 200 @Override 201 public PEBuilder getProfiledElementBuilder( 202 PEBuilder.PEElementPropertiesPolicy thePEElementPropertiesPolicy, boolean theB) { 203 throw new UnsupportedOperationException(Msg.code(2264)); 204 } 205 206 @Override 207 public PackageInformation getPackageForUrl(String s) { 208 throw new UnsupportedOperationException(Msg.code(2236)); 209 } 210 211 @Override 212 public org.hl7.fhir.r5.model.Parameters getExpansionParameters() { 213 return myExpansionProfile; 214 } 215 216 @Override 217 public void setExpansionProfile(org.hl7.fhir.r5.model.Parameters expParameters) { 218 myExpansionProfile = expParameters; 219 } 220 221 private List<StructureDefinition> allStructures() { 222 223 List<StructureDefinition> retVal = myAllStructures; 224 if (retVal == null) { 225 retVal = new ArrayList<>(); 226 for (IBaseResource next : 227 myValidationSupportContext.getRootValidationSupport().fetchAllStructureDefinitions()) { 228 try { 229 StructureDefinition converted = myVersionCanonicalizer.structureDefinitionToCanonical(next); 230 retVal.add(converted); 231 } catch (FHIRException e) { 232 throw new InternalErrorException(Msg.code(659) + e); 233 } 234 } 235 myAllStructures = retVal; 236 } 237 238 return retVal; 239 } 240 241 @Override 242 public void cacheResource(Resource res) {} 243 244 @Override 245 public void cacheResourceFromPackage(Resource res, PackageInformation packageDetails) throws FHIRException {} 246 247 @Override 248 public void cachePackage(PackageInformation packageInformation) {} 249 250 @Nonnull 251 private ValidationResult convertValidationResult( 252 String theSystem, @Nullable IValidationSupport.CodeValidationResult theResult) { 253 ValidationResult retVal = null; 254 if (theResult != null) { 255 String code = theResult.getCode(); 256 String display = theResult.getDisplay(); 257 258 String issueSeverityCode = theResult.getSeverityCode(); 259 String message = theResult.getMessage(); 260 ValidationMessage.IssueSeverity issueSeverity = null; 261 if (issueSeverityCode != null) { 262 issueSeverity = ValidationMessage.IssueSeverity.fromCode(issueSeverityCode); 263 } else if (isNotBlank(message)) { 264 issueSeverity = ValidationMessage.IssueSeverity.INFORMATION; 265 } 266 267 CodeSystem.ConceptDefinitionComponent conceptDefinitionComponent = null; 268 if (code != null) { 269 conceptDefinitionComponent = new CodeSystem.ConceptDefinitionComponent() 270 .setCode(code) 271 .setDisplay(display); 272 } 273 274 retVal = new ValidationResult( 275 issueSeverity, 276 message, 277 theSystem, 278 theResult.getCodeSystemVersion(), 279 conceptDefinitionComponent, 280 display, 281 null); 282 } 283 284 if (retVal == null) { 285 retVal = new ValidationResult(ValidationMessage.IssueSeverity.ERROR, "Validation failed", null); 286 } 287 288 return retVal; 289 } 290 291 @Override 292 public ValueSetExpansionOutcome expandVS( 293 org.hl7.fhir.r5.model.ValueSet source, boolean cacheOk, boolean Hierarchical) { 294 IBaseResource convertedSource; 295 try { 296 convertedSource = myVersionCanonicalizer.valueSetFromValidatorCanonical(source); 297 } catch (FHIRException e) { 298 throw new InternalErrorException(Msg.code(661) + e); 299 } 300 IValidationSupport.ValueSetExpansionOutcome expanded = myValidationSupportContext 301 .getRootValidationSupport() 302 .expandValueSet(myValidationSupportContext, null, convertedSource); 303 304 org.hl7.fhir.r5.model.ValueSet convertedResult = null; 305 if (expanded.getValueSet() != null) { 306 try { 307 convertedResult = myVersionCanonicalizer.valueSetToValidatorCanonical(expanded.getValueSet()); 308 } catch (FHIRException e) { 309 throw new InternalErrorException(Msg.code(662) + e); 310 } 311 } 312 313 String error = expanded.getError(); 314 TerminologyServiceErrorClass result = null; 315 316 return new ValueSetExpansionOutcome(convertedResult, error, result); 317 } 318 319 @Override 320 public ValueSetExpansionOutcome expandVS( 321 Resource src, 322 org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent binding, 323 boolean cacheOk, 324 boolean Hierarchical) { 325 throw new UnsupportedOperationException(Msg.code(663)); 326 } 327 328 @Override 329 public ValueSetExpansionOutcome expandVS(ValueSet.ConceptSetComponent inc, boolean hierarchical, boolean noInactive) 330 throws TerminologyServiceException { 331 throw new UnsupportedOperationException(Msg.code(664)); 332 } 333 334 @Override 335 public Locale getLocale() { 336 return myValidationSupportContext 337 .getRootValidationSupport() 338 .getFhirContext() 339 .getLocalizer() 340 .getLocale(); 341 } 342 343 @Override 344 public void setLocale(Locale locale) { 345 // ignore 346 } 347 348 @Override 349 public org.hl7.fhir.r5.model.CodeSystem fetchCodeSystem(String system) { 350 IBaseResource fetched = 351 myValidationSupportContext.getRootValidationSupport().fetchCodeSystem(system); 352 if (fetched == null) { 353 return null; 354 } 355 try { 356 return (org.hl7.fhir.r5.model.CodeSystem) myVersionCanonicalizer.codeSystemToValidatorCanonical(fetched); 357 } catch (FHIRException e) { 358 throw new InternalErrorException(Msg.code(665) + e); 359 } 360 } 361 362 @Override 363 public CodeSystem fetchCodeSystem(String system, String verison) { 364 IBaseResource fetched = 365 myValidationSupportContext.getRootValidationSupport().fetchCodeSystem(system); 366 if (fetched == null) { 367 return null; 368 } 369 try { 370 return (org.hl7.fhir.r5.model.CodeSystem) myVersionCanonicalizer.codeSystemToValidatorCanonical(fetched); 371 } catch (FHIRException e) { 372 throw new InternalErrorException(Msg.code(1992) + e); 373 } 374 } 375 376 @Override 377 public CodeSystem fetchSupplementedCodeSystem(String system) { 378 return null; 379 } 380 381 @Override 382 public CodeSystem fetchSupplementedCodeSystem(String system, String version) { 383 return null; 384 } 385 386 @Override 387 public <T extends Resource> T fetchResourceRaw(Class<T> class_, String uri) { 388 return fetchResource(class_, uri); 389 } 390 391 @Override 392 public <T extends Resource> T fetchResource(Class<T> class_, String uri) { 393 394 if (isBlank(uri)) { 395 return null; 396 } 397 398 ResourceKey key = new ResourceKey(class_.getSimpleName(), uri); 399 @SuppressWarnings("unchecked") 400 T retVal = (T) myFetchResourceCache.get(key); 401 402 return retVal; 403 } 404 405 @Override 406 public Resource fetchResourceById(String type, String uri) { 407 throw new UnsupportedOperationException(Msg.code(666)); 408 } 409 410 @Override 411 public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException { 412 T retVal = fetchResource(class_, uri); 413 if (retVal == null) { 414 throw new FHIRException( 415 Msg.code(667) + "Can not find resource of type " + class_.getSimpleName() + " with uri " + uri); 416 } 417 return retVal; 418 } 419 420 @Override 421 public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version) { 422 return fetchResource(class_, uri + "|" + version); 423 } 424 425 @Override 426 public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource canonicalForSource) { 427 return fetchResource(class_, uri); 428 } 429 430 @Override 431 public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceOfReference) 432 throws FHIRException { 433 throw new UnsupportedOperationException(Msg.code(2214)); 434 } 435 436 @Override 437 public List<String> getResourceNames() { 438 return new ArrayList<>(myValidationSupportContext 439 .getRootValidationSupport() 440 .getFhirContext() 441 .getResourceTypes()); 442 } 443 444 @Override 445 public Set<String> getResourceNamesAsSet() { 446 return myValidationSupportContext 447 .getRootValidationSupport() 448 .getFhirContext() 449 .getResourceTypes(); 450 } 451 452 @Override 453 public StructureDefinition fetchTypeDefinition(String typeName) { 454 return fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName); 455 } 456 457 @Override 458 public List<StructureDefinition> fetchTypeDefinitions(String typeName) { 459 List<StructureDefinition> allStructures = new ArrayList<>(allStructures()); 460 allStructures.removeIf(sd -> !sd.hasType() || !sd.getType().equals(typeName)); 461 return allStructures; 462 } 463 464 @Override 465 public UcumService getUcumService() { 466 throw new UnsupportedOperationException(Msg.code(676)); 467 } 468 469 @Override 470 public void setUcumService(UcumService ucumService) { 471 throw new UnsupportedOperationException(Msg.code(677)); 472 } 473 474 @Override 475 public String getVersion() { 476 return myValidationSupportContext 477 .getRootValidationSupport() 478 .getFhirContext() 479 .getVersion() 480 .getVersion() 481 .getFhirVersionString(); 482 } 483 484 @Override 485 public <T extends Resource> boolean hasResource(Class<T> class_, String uri) { 486 throw new UnsupportedOperationException(Msg.code(680)); 487 } 488 489 @Override 490 public boolean isNoTerminologyServer() { 491 return false; 492 } 493 494 @Override 495 public Set<String> getCodeSystemsUsed() { 496 throw new UnsupportedOperationException(Msg.code(681)); 497 } 498 499 @Override 500 public IResourceValidator newValidator() { 501 throw new UnsupportedOperationException(Msg.code(684)); 502 } 503 504 @Override 505 public Map<String, NamingSystem> getNSUrlMap() { 506 throw new UnsupportedOperationException(Msg.code(2265)); 507 } 508 509 @Override 510 public ILoggingService getLogger() { 511 return null; 512 } 513 514 @Override 515 public void setLogger(ILoggingService logger) { 516 throw new UnsupportedOperationException(Msg.code(687)); 517 } 518 519 @Override 520 public boolean supportsSystem(String system) { 521 return myValidationSupportContext 522 .getRootValidationSupport() 523 .isCodeSystemSupported(myValidationSupportContext, system); 524 } 525 526 @Override 527 public TranslationServices translator() { 528 throw new UnsupportedOperationException(Msg.code(688)); 529 } 530 531 @Override 532 public ValueSetExpansionOutcome expandVS( 533 ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk) { 534 return null; 535 } 536 537 @Override 538 public ValidationResult validateCode( 539 ValidationOptions theOptions, String system, String version, String code, String display) { 540 ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions); 541 return doValidation(null, validationOptions, system, code, display); 542 } 543 544 @Override 545 public ValidationResult validateCode( 546 ValidationOptions theOptions, 547 String theSystem, 548 String version, 549 String theCode, 550 String display, 551 ValueSet theValueSet) { 552 IBaseResource convertedVs = null; 553 554 try { 555 if (theValueSet != null) { 556 convertedVs = myVersionCanonicalizer.valueSetFromValidatorCanonical(theValueSet); 557 } 558 } catch (FHIRException e) { 559 throw new InternalErrorException(Msg.code(689) + e); 560 } 561 562 ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions); 563 564 return doValidation(convertedVs, validationOptions, theSystem, theCode, display); 565 } 566 567 @Override 568 public ValidationResult validateCode( 569 ValidationOptions theOptions, String code, org.hl7.fhir.r5.model.ValueSet theValueSet) { 570 IBaseResource convertedVs = null; 571 try { 572 if (theValueSet != null) { 573 convertedVs = myVersionCanonicalizer.valueSetFromValidatorCanonical(theValueSet); 574 } 575 } catch (FHIRException e) { 576 throw new InternalErrorException(Msg.code(690) + e); 577 } 578 579 ConceptValidationOptions validationOptions = 580 convertConceptValidationOptions(theOptions).setInferSystem(true); 581 582 return doValidation(convertedVs, validationOptions, null, code, null); 583 } 584 585 @Override 586 public ValidationResult validateCode( 587 ValidationOptions theOptions, 588 org.hl7.fhir.r5.model.Coding theCoding, 589 org.hl7.fhir.r5.model.ValueSet theValueSet) { 590 IBaseResource convertedVs = null; 591 592 try { 593 if (theValueSet != null) { 594 convertedVs = myVersionCanonicalizer.valueSetFromValidatorCanonical(theValueSet); 595 } 596 } catch (FHIRException e) { 597 throw new InternalErrorException(Msg.code(691) + e); 598 } 599 600 ConceptValidationOptions validationOptions = convertConceptValidationOptions(theOptions); 601 String system = theCoding.getSystem(); 602 String code = theCoding.getCode(); 603 String display = theCoding.getDisplay(); 604 605 return doValidation(convertedVs, validationOptions, system, code, display); 606 } 607 608 @Override 609 public ValidationResult validateCode( 610 ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt) { 611 return validateCode(options, code, vs); 612 } 613 614 @Override 615 public void validateCodeBatch( 616 ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs) { 617 for (CodingValidationRequest next : codes) { 618 ValidationResult outcome = validateCode(options, next.getCoding(), vs); 619 next.setResult(outcome); 620 } 621 } 622 623 @Override 624 public void validateCodeBatchByRef( 625 ValidationOptions validationOptions, List<? extends CodingValidationRequest> list, String s) { 626 ValueSet valueSet = fetchResource(ValueSet.class, s); 627 validateCodeBatch(validationOptions, list, valueSet); 628 } 629 630 @Nonnull 631 private ValidationResult doValidation( 632 IBaseResource theValueSet, 633 ConceptValidationOptions theValidationOptions, 634 String theSystem, 635 String theCode, 636 String theDisplay) { 637 IValidationSupport.CodeValidationResult result; 638 if (theValueSet != null) { 639 result = myValidationSupportContext 640 .getRootValidationSupport() 641 .validateCodeInValueSet( 642 myValidationSupportContext, 643 theValidationOptions, 644 theSystem, 645 theCode, 646 theDisplay, 647 theValueSet); 648 } else { 649 result = myValidationSupportContext 650 .getRootValidationSupport() 651 .validateCode( 652 myValidationSupportContext, theValidationOptions, theSystem, theCode, theDisplay, null); 653 } 654 return convertValidationResult(theSystem, result); 655 } 656 657 @Override 658 public ValidationResult validateCode( 659 ValidationOptions theOptions, 660 org.hl7.fhir.r5.model.CodeableConcept code, 661 org.hl7.fhir.r5.model.ValueSet theVs) { 662 List<ValidationResult> validationResultsOk = new ArrayList<>(); 663 for (Coding next : code.getCoding()) { 664 ValidationResult retVal = validateCode(theOptions, next, theVs); 665 if (retVal.isOk()) { 666 if (myValidationSupportContext.isEnabledValidationForCodingsLogicalAnd()) { 667 validationResultsOk.add(retVal); 668 } else { 669 return retVal; 670 } 671 } 672 } 673 674 if (code.getCoding().size() > 0 675 && validationResultsOk.size() == code.getCoding().size()) { 676 return validationResultsOk.get(0); 677 } 678 679 return new ValidationResult(ValidationMessage.IssueSeverity.ERROR, null, null); 680 } 681 682 public void invalidateCaches() { 683 myFetchResourceCache.invalidateAll(); 684 } 685 686 @Override 687 public <T extends Resource> List<T> fetchResourcesByType(Class<T> theClass) { 688 if (theClass.equals(StructureDefinition.class)) { 689 return (List<T>) allStructures(); 690 } 691 throw new UnsupportedOperationException(Msg.code(650) + "Unable to fetch resources of type: " + theClass); 692 } 693 694 @Override 695 public boolean isForPublication() { 696 return false; 697 } 698 699 @Override 700 public void setForPublication(boolean b) { 701 throw new UnsupportedOperationException(Msg.code(2351)); 702 } 703 704 public static ConceptValidationOptions convertConceptValidationOptions(ValidationOptions theOptions) { 705 ConceptValidationOptions retVal = new ConceptValidationOptions(); 706 if (theOptions.isGuessSystem()) { 707 retVal = retVal.setInferSystem(true); 708 } 709 return retVal; 710 } 711 712 @Nonnull 713 public static VersionSpecificWorkerContextWrapper newVersionSpecificWorkerContextWrapper( 714 IValidationSupport theValidationSupport) { 715 VersionCanonicalizer versionCanonicalizer = new VersionCanonicalizer(theValidationSupport.getFhirContext()); 716 return new VersionSpecificWorkerContextWrapper( 717 new ValidationSupportContext(theValidationSupport), versionCanonicalizer); 718 } 719 720 private static class ResourceKey { 721 private final int myHashCode; 722 private final String myResourceName; 723 private final String myUri; 724 725 private ResourceKey(String theResourceName, String theUri) { 726 myResourceName = theResourceName; 727 myUri = theUri; 728 myHashCode = new HashCodeBuilder(17, 37) 729 .append(myResourceName) 730 .append(myUri) 731 .toHashCode(); 732 } 733 734 @Override 735 public boolean equals(Object theO) { 736 if (this == theO) { 737 return true; 738 } 739 740 if (theO == null || getClass() != theO.getClass()) { 741 return false; 742 } 743 744 ResourceKey that = (ResourceKey) theO; 745 746 return new EqualsBuilder() 747 .append(myResourceName, that.myResourceName) 748 .append(myUri, that.myUri) 749 .isEquals(); 750 } 751 752 public String getResourceName() { 753 return myResourceName; 754 } 755 756 public String getUri() { 757 return myUri; 758 } 759 760 @Override 761 public int hashCode() { 762 return myHashCode; 763 } 764 } 765}