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