
001package org.hl7.fhir.r5.hapi.ctx; 002 003import ca.uhn.fhir.context.FhirContext; 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.api.Constants; 009import ca.uhn.fhir.sl.cache.Cache; 010import ca.uhn.fhir.sl.cache.CacheFactory; 011import ca.uhn.fhir.system.HapiSystemProperties; 012import org.apache.commons.lang3.Validate; 013import org.fhir.ucum.UcumService; 014import org.hl7.fhir.exceptions.FHIRException; 015import org.hl7.fhir.exceptions.TerminologyServiceException; 016import org.hl7.fhir.r5.context.IContextResourceLoader; 017import org.hl7.fhir.r5.context.IWorkerContext; 018import org.hl7.fhir.r5.context.IWorkerContextManager; 019import org.hl7.fhir.r5.model.CodeSystem; 020import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; 021import org.hl7.fhir.r5.model.CodeableConcept; 022import org.hl7.fhir.r5.model.Coding; 023import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; 024import org.hl7.fhir.r5.model.NamingSystem; 025import org.hl7.fhir.r5.model.OperationOutcome; 026import org.hl7.fhir.r5.model.PackageInformation; 027import org.hl7.fhir.r5.model.Parameters; 028import org.hl7.fhir.r5.model.Resource; 029import org.hl7.fhir.r5.model.ResourceType; 030import org.hl7.fhir.r5.model.StructureDefinition; 031import org.hl7.fhir.r5.model.ValueSet; 032import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; 033import org.hl7.fhir.r5.profilemodel.PEBuilder; 034import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; 035import org.hl7.fhir.r5.terminologies.utilities.CodingValidationRequest; 036import org.hl7.fhir.r5.terminologies.utilities.ValidationResult; 037import org.hl7.fhir.r5.utils.validation.IResourceValidator; 038import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier; 039import org.hl7.fhir.utilities.FhirPublication; 040import org.hl7.fhir.utilities.TimeTracker; 041import org.hl7.fhir.utilities.i18n.I18nBase; 042import org.hl7.fhir.utilities.npm.BasePackageCacheManager; 043import org.hl7.fhir.utilities.npm.NpmPackage; 044import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; 045import org.hl7.fhir.utilities.validation.ValidationOptions; 046 047import java.util.ArrayList; 048import java.util.Collections; 049import java.util.List; 050import java.util.Locale; 051import java.util.Map; 052import java.util.Set; 053 054import static org.apache.commons.lang3.StringUtils.isNotBlank; 055 056public final class HapiWorkerContext extends I18nBase implements IWorkerContext { 057 private final FhirContext myCtx; 058 private final Cache<String, Resource> myFetchedResourceCache; 059 private final IValidationSupport myValidationSupport; 060 private Parameters myExpansionProfile; 061 private String myOverrideVersionNs; 062 063 public HapiWorkerContext(FhirContext theCtx, IValidationSupport theValidationSupport) { 064 Validate.notNull(theCtx, "theCtx must not be null"); 065 Validate.notNull(theValidationSupport, "theValidationSupport must not be null"); 066 myCtx = theCtx; 067 myValidationSupport = theValidationSupport; 068 069 long timeoutMillis = HapiSystemProperties.getValidationResourceCacheTimeoutMillis(); 070 071 myFetchedResourceCache = CacheFactory.build(timeoutMillis); 072 073 // Set a default locale 074 setValidationMessageLanguage(getLocale()); 075 } 076 077 @Override 078 public CodeSystem fetchCodeSystem(String theSystem) { 079 if (myValidationSupport == null) { 080 return null; 081 } else { 082 return (CodeSystem) myValidationSupport.fetchCodeSystem(theSystem); 083 } 084 } 085 086 @Override 087 public CodeSystem fetchCodeSystem(String theSystem, String version) { 088 if (myValidationSupport == null) { 089 return null; 090 } else { 091 return (CodeSystem) myValidationSupport.fetchCodeSystem(theSystem); 092 } 093 } 094 095 @Override 096 public CodeSystem fetchCodeSystem(String system, FhirPublication fhirVersion) { 097 throw new UnsupportedOperationException(Msg.code(2456)); 098 } 099 100 @Override 101 public CodeSystem fetchCodeSystem(String system, String version, FhirPublication fhirVersion) { 102 throw new UnsupportedOperationException(Msg.code(2457)); 103 } 104 105 @Override 106 public CodeSystem fetchSupplementedCodeSystem(String theS) { 107 return null; 108 } 109 110 @Override 111 public CodeSystem fetchSupplementedCodeSystem(String theS, String theS1) { 112 return null; 113 } 114 115 @Override 116 public CodeSystem fetchSupplementedCodeSystem(String system, FhirPublication fhirVersion) { 117 throw new UnsupportedOperationException(Msg.code(2458)); 118 } 119 120 @Override 121 public CodeSystem fetchSupplementedCodeSystem(String system, String version, FhirPublication fhirVersion) { 122 throw new UnsupportedOperationException(Msg.code(2459)); 123 } 124 125 @Override 126 public List<String> getResourceNames() { 127 List<String> result = new ArrayList<>(); 128 for (ResourceType next : ResourceType.values()) { 129 result.add(next.name()); 130 } 131 Collections.sort(result); 132 return result; 133 } 134 135 @Override 136 public List<String> getResourceNames(FhirPublication fhirVersion) { 137 throw new UnsupportedOperationException(Msg.code(2460)); 138 } 139 140 @Override 141 public IResourceValidator newValidator() { 142 throw new UnsupportedOperationException(Msg.code(206)); 143 } 144 145 @Override 146 public Map<String, NamingSystem> getNSUrlMap() { 147 throw new UnsupportedOperationException(Msg.code(2241)); 148 } 149 150 @Override 151 public boolean supportsSystem(String theSystem) { 152 if (myValidationSupport == null) { 153 return false; 154 } else { 155 return myValidationSupport.isCodeSystemSupported( 156 new ValidationSupportContext(myValidationSupport), theSystem); 157 } 158 } 159 160 @Override 161 public boolean supportsSystem(String system, FhirPublication fhirVersion) throws TerminologyServiceException { 162 if (!fhirVersion.equals(FhirPublication.R5)) { 163 throw new UnsupportedOperationException(Msg.code(2461)); 164 } 165 return supportsSystem(system); 166 } 167 168 @Override 169 public SystemSupportInformation getTxSupportInfo(String system, String version) { 170 return null; 171 } 172 173 @Override 174 public SystemSupportInformation getTxSupportInfo(String system) { 175 return null; 176 } 177 178 @Override 179 public ValidationResult validateCode(ValidationOptions theOptions, CodeableConcept theCode, ValueSet theVs) { 180 for (Coding next : theCode.getCoding()) { 181 ValidationResult retVal = validateCode(theOptions, next, theVs); 182 if (retVal.isOk()) { 183 return retVal; 184 } 185 } 186 187 return new ValidationResult(IssueSeverity.ERROR, null, null); 188 } 189 190 @Override 191 public ValidationResult validateCode(ValidationOptions theOptions, Coding theCode, ValueSet theVs) { 192 String system = theCode.getSystem(); 193 String code = theCode.getCode(); 194 String display = theCode.getDisplay(); 195 return validateCode(theOptions, system, null, code, display, theVs); 196 } 197 198 @Override 199 public ValidationResult validateCode( 200 ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt) { 201 return validateCode(options, code, vs); 202 } 203 204 @Override 205 public void validateCodeBatch( 206 ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs, boolean passVS) {} 207 208 @Override 209 public ValueSetExpansionOutcome expandVS( 210 ValueSet theValueSet, boolean cacheOk, boolean heiarchical, boolean incompleteOk) { 211 return null; 212 } 213 214 @Override 215 public ValueSetExpansionOutcome expandVS(String s, boolean b, boolean b1, int i) { 216 return null; 217 } 218 219 @Override 220 public ValidationResult validateCode( 221 ValidationOptions theOptions, String theSystem, String theVersion, String theCode, String theDisplay) { 222 IValidationSupport.CodeValidationResult result = myValidationSupport.validateCode( 223 new ValidationSupportContext(myValidationSupport), 224 convertConceptValidationOptions(theOptions), 225 theSystem, 226 theCode, 227 theDisplay, 228 null); 229 if (result == null) { 230 return null; 231 } 232 IssueSeverity severity = null; 233 if (result.getSeverity() != null) { 234 severity = IssueSeverity.fromCode(result.getSeverityCode()); 235 } 236 ConceptDefinitionComponent definition = new ConceptDefinitionComponent().setCode(result.getCode()); 237 return new ValidationResult(severity, result.getMessage(), theSystem, theVersion, definition, null, null); 238 } 239 240 @Override 241 public ValidationResult validateCode( 242 ValidationOptions theOptions, 243 String theSystem, 244 String theVersion, 245 String theCode, 246 String theDisplay, 247 ValueSet theVs) { 248 IValidationSupport.CodeValidationResult outcome; 249 if (isNotBlank(theVs.getUrl())) { 250 outcome = myValidationSupport.validateCode( 251 new ValidationSupportContext(myValidationSupport), 252 convertConceptValidationOptions(theOptions), 253 theSystem, 254 theCode, 255 theDisplay, 256 theVs.getUrl()); 257 } else { 258 outcome = myValidationSupport.validateCodeInValueSet( 259 new ValidationSupportContext(myValidationSupport), 260 convertConceptValidationOptions(theOptions), 261 theSystem, 262 theCode, 263 theDisplay, 264 theVs); 265 } 266 267 if (outcome != null && outcome.isOk()) { 268 ConceptDefinitionComponent definition = new ConceptDefinitionComponent(); 269 definition.setCode(theCode); 270 definition.setDisplay(outcome.getDisplay()); 271 return new ValidationResult(theSystem, theVersion, definition, null); 272 } 273 274 return new ValidationResult( 275 IssueSeverity.ERROR, 276 "Unknown code[" + theCode + "] in system[" + Constants.codeSystemWithDefaultDescription(theSystem) 277 + "]", 278 null); 279 } 280 281 @Override 282 public ValidationResult validateCode(ValidationOptions theOptions, String code, ValueSet vs) { 283 return validateCode(theOptions, null, null, code, null, vs); 284 } 285 286 @Override 287 public Parameters getExpansionParameters() { 288 return myExpansionProfile; 289 } 290 291 @Override 292 public void setExpansionParameters(Parameters expParameters) { 293 setExpansionProfile(expParameters); 294 } 295 296 public void setExpansionProfile(Parameters theExpParameters) { 297 myExpansionProfile = theExpParameters; 298 } 299 300 @Override 301 public ValueSetExpansionOutcome expandVS(ValueSet theSource, boolean theCacheOk, boolean theHierarchical) { 302 throw new UnsupportedOperationException(Msg.code(2128)); 303 } 304 305 @Override 306 public ValueSetExpansionOutcome expandVS(ValueSet theSource, boolean theCacheOk, boolean theHierarchical, int i) { 307 throw new UnsupportedOperationException(Msg.code(2650)); 308 } 309 310 /*1@Override 311 public ValueSetExpansionOutcome expandVS(ConceptSetComponent theInc, boolean theHierarchical, boolean theNoInactive) 312 throws TerminologyServiceException { 313 ValueSet input = new ValueSet(); 314 input.getCompose().setInactive(!theNoInactive); // TODO GGG/DO is this valid? 315 input.getCompose().addInclude(theInc); 316 IValidationSupport.ValueSetExpansionOutcome output = 317 myValidationSupport.expandValueSet(new ValidationSupportContext(myValidationSupport), null, input); 318 return new ValueSetExpansionOutcome( 319 (ValueSet) output.getValueSet(), output.getError(), null, output.getErrorIsFromServer()); 320 }*/ 321 322 @Override 323 public Locale getLocale() { 324 return Locale.getDefault(); 325 } 326 327 @Override 328 public void setLocale(Locale locale) { 329 // ignore 330 } 331 332 @Override 333 public org.hl7.fhir.r5.context.ILoggingService getLogger() { 334 throw new UnsupportedOperationException(Msg.code(213)); 335 } 336 337 @Override 338 public void setLogger(org.hl7.fhir.r5.context.ILoggingService theLogger) { 339 throw new UnsupportedOperationException(Msg.code(214)); 340 } 341 342 @Override 343 public String getVersion() { 344 return myCtx.getVersion().getVersion().getFhirVersionString(); 345 } 346 347 @Override 348 public UcumService getUcumService() { 349 throw new UnsupportedOperationException(Msg.code(216)); 350 } 351 352 @Override 353 public void setUcumService(UcumService ucumService) { 354 throw new UnsupportedOperationException(Msg.code(217)); 355 } 356 357 @Override 358 public boolean isNoTerminologyServer() { 359 return false; 360 } 361 362 @Override 363 public Set<String> getCodeSystemsUsed() { 364 throw new UnsupportedOperationException(Msg.code(218)); 365 } 366 367 @Override 368 public StructureDefinition fetchTypeDefinition(String typeName) { 369 return fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/" + typeName); 370 } 371 372 @Override 373 public boolean isPrimitiveType(String s) { 374 throw new UnsupportedOperationException(Msg.code(2462)); 375 } 376 377 @Override 378 public boolean isDataType(String s) { 379 throw new UnsupportedOperationException(Msg.code(2463)); 380 } 381 382 @Override 383 public StructureDefinition fetchTypeDefinition(String typeName, FhirPublication fhirVersion) { 384 throw new UnsupportedOperationException(Msg.code(2464)); 385 } 386 387 @Override 388 public List<StructureDefinition> fetchTypeDefinitions(String n) { 389 throw new UnsupportedOperationException(Msg.code(234)); 390 } 391 392 @Override 393 public List<StructureDefinition> fetchTypeDefinitions(String n, FhirPublication fhirPublication) { 394 throw new UnsupportedOperationException(Msg.code(2465)); 395 } 396 397 @Override 398 public <T extends Resource> T fetchResourceRaw(Class<T> class_, String uri) { 399 return fetchResource(class_, uri); 400 } 401 402 @Override 403 public <T extends org.hl7.fhir.r5.model.Resource> T fetchResource(Class<T> theClass, String theUri) { 404 if (myValidationSupport == null || theUri == null) { 405 return null; 406 } else { 407 @SuppressWarnings("unchecked") 408 T retVal = (T) myFetchedResourceCache.get(theUri, t -> myValidationSupport.fetchResource(theClass, theUri)); 409 return retVal; 410 } 411 } 412 413 public <T extends Resource> T fetchResource(Class<T> class_, String uri, FhirPublication fhirVersion) { 414 throw new UnsupportedOperationException(Msg.code(2466)); 415 } 416 417 @Override 418 public <T extends org.hl7.fhir.r5.model.Resource> T fetchResourceWithException(Class<T> theClass, String theUri) 419 throws FHIRException { 420 T retVal = fetchResource(theClass, theUri); 421 if (retVal == null) { 422 throw new FHIRException(Msg.code(224) + "Could not find resource: " + theUri); 423 } 424 return retVal; 425 } 426 427 @Override 428 public <T extends Resource> T fetchResourceWithException(Class<T> theClass, String uri, Resource sourceOfReference) 429 throws FHIRException { 430 throw new UnsupportedOperationException(Msg.code(2213)); 431 } 432 433 @Override 434 public <T extends Resource> T fetchResource(Class<T> theClass, String theUri, String theVersion) { 435 return fetchResource(theClass, theUri + "|" + theVersion); 436 } 437 438 @Override 439 public <T extends Resource> T fetchResource( 440 Class<T> class_, String uri, String version, FhirPublication fhirVersion) { 441 throw new UnsupportedOperationException(Msg.code(2467)); 442 } 443 444 @Override 445 public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource canonicalForSource) { 446 return fetchResource(class_, uri); 447 } 448 449 @Override 450 public <T extends Resource> List<T> fetchResourcesByType(Class<T> class_, FhirPublication fhirVersion) { 451 throw new UnsupportedOperationException(Msg.code(2468)); 452 } 453 454 @Override 455 public org.hl7.fhir.r5.model.Resource fetchResourceById(String theType, String theUri) { 456 throw new UnsupportedOperationException(Msg.code(226)); 457 } 458 459 @Override 460 public Resource fetchResourceById(String type, String uri, FhirPublication fhirVersion) { 461 throw new UnsupportedOperationException(Msg.code(2469)); 462 } 463 464 @Override 465 public <T extends org.hl7.fhir.r5.model.Resource> boolean hasResource(Class<T> theClass_, String theUri) { 466 throw new UnsupportedOperationException(Msg.code(227)); 467 } 468 469 @Override 470 public <T extends Resource> boolean hasResource(Class<T> class_, String uri, Resource sourceOfReference) { 471 throw new UnsupportedOperationException(Msg.code(2470)); 472 } 473 474 @Override 475 public <T extends Resource> boolean hasResource(Class<T> class_, String uri, FhirPublication fhirVersion) { 476 throw new UnsupportedOperationException(Msg.code(2471)); 477 } 478 479 @Override 480 public void cacheResource(org.hl7.fhir.r5.model.Resource theRes) throws FHIRException { 481 throw new UnsupportedOperationException(Msg.code(228)); 482 } 483 484 @Override 485 public void cacheResourceFromPackage(Resource res, PackageInformation packageDetails) throws FHIRException { 486 throw new UnsupportedOperationException(Msg.code(229)); 487 } 488 489 @Override 490 public void cachePackage(PackageInformation packageInformation) {} 491 492 @Override 493 public Set<String> getResourceNamesAsSet() { 494 return myCtx.getResourceTypes(); 495 } 496 497 @Override 498 public Set<String> getResourceNamesAsSet(FhirPublication fhirVersion) { 499 throw new UnsupportedOperationException(Msg.code(2472)); 500 } 501 502 @Override 503 public ValueSetExpansionOutcome expandVS( 504 Resource src, ElementDefinitionBindingComponent theBinding, boolean theCacheOk, boolean theHierarchical) 505 throws FHIRException { 506 throw new UnsupportedOperationException(Msg.code(230)); 507 } 508 509 @Override 510 public ValueSetExpansionOutcome expandVS( 511 ITerminologyOperationDetails iTerminologyOperationDetails, 512 ConceptSetComponent conceptSetComponent, 513 boolean b, 514 boolean b1) 515 throws TerminologyServiceException { 516 return null; 517 } 518 519 @Override 520 public Set<String> getBinaryKeysAsSet() { 521 throw new UnsupportedOperationException(Msg.code(2115)); 522 } 523 524 @Override 525 public boolean hasBinaryKey(String s) { 526 throw new UnsupportedOperationException(Msg.code(2129)); 527 } 528 529 @Override 530 public byte[] getBinaryForKey(String s) { 531 throw new UnsupportedOperationException(Msg.code(2199)); 532 } 533 534 @Override 535 public int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FHIRException { 536 throw new UnsupportedOperationException(Msg.code(233)); 537 } 538 539 @Override 540 public int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) 541 throws FHIRException { 542 throw new UnsupportedOperationException(Msg.code(235)); 543 } 544 545 @Override 546 public boolean hasPackage(String id, String ver) { 547 throw new UnsupportedOperationException(Msg.code(236)); 548 } 549 550 @Override 551 public boolean hasPackage(PackageInformation packageVersion) { 552 return false; 553 } 554 555 @Override 556 public PackageInformation getPackage(String id, String ver) { 557 return null; 558 } 559 560 @Override 561 public int getClientRetryCount() { 562 throw new UnsupportedOperationException(Msg.code(237)); 563 } 564 565 @Override 566 public IWorkerContext setClientRetryCount(int value) { 567 throw new UnsupportedOperationException(Msg.code(238)); 568 } 569 570 @Override 571 public TimeTracker clock() { 572 return null; 573 } 574 575 @Override 576 public IWorkerContextManager.IPackageLoadingTracker getPackageTracker() { 577 throw new UnsupportedOperationException(Msg.code(2112)); 578 } 579 580 @Override 581 public PackageInformation getPackageForUrl(String s) { 582 return null; 583 } 584 585 public static ConceptValidationOptions convertConceptValidationOptions(ValidationOptions theOptions) { 586 ConceptValidationOptions retVal = new ConceptValidationOptions(); 587 if (theOptions.isGuessSystem()) { 588 retVal = retVal.setInferSystem(true); 589 } 590 return retVal; 591 } 592 593 @Override 594 public <T extends Resource> List<T> fetchResourcesByType(Class<T> theClass) { 595 if (theClass.equals(StructureDefinition.class)) { 596 return myValidationSupport.fetchAllStructureDefinitions(); 597 } 598 599 throw new UnsupportedOperationException(Msg.code(2113) + "Can't fetch all resources of type: " + theClass); 600 } 601 602 @Override 603 public <T extends Resource> List<T> fetchResourceVersionsByTypeAndUrl(Class<T> class_, String url) { 604 throw new UnsupportedOperationException( 605 Msg.code(2796) + "Can't fetch all resources of type : " + class_ + " and url: " + url); 606 } 607 608 @Override 609 public <T extends Resource> List<T> fetchResourcesByUrl(Class<T> class_, String url) { 610 throw new UnsupportedOperationException(Msg.code(2508) + "Can't fetch all resources of url: " + url); 611 } 612 613 @Override 614 public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker theIPackageLoadingTracker) { 615 throw new UnsupportedOperationException(Msg.code(220)); 616 } 617 618 @Override 619 public String getSpecUrl() { 620 return ""; 621 } 622 623 @Override 624 public PEBuilder getProfiledElementBuilder( 625 PEBuilder.PEElementPropertiesPolicy thePEElementPropertiesPolicy, boolean theB) { 626 throw new UnsupportedOperationException(Msg.code(2261)); 627 } 628 629 @Override 630 public boolean isForPublication() { 631 return false; 632 } 633 634 @Override 635 public void setForPublication(boolean b) { 636 throw new UnsupportedOperationException(Msg.code(2350)); 637 } 638 639 @Override 640 public OIDSummary urlsForOid(String oid, String resourceType) { 641 throw new UnsupportedOperationException(Msg.code(2473)); 642 } 643 644 @Override 645 public <T extends Resource> T findTxResource(Class<T> class_, String canonical, Resource sourceOfReference) { 646 throw new UnsupportedOperationException(Msg.code(2491)); 647 } 648 649 @Override 650 public <T extends Resource> T findTxResource(Class<T> class_, String canonical) { 651 throw new UnsupportedOperationException(Msg.code(2492)); 652 } 653 654 @Override 655 public <T extends Resource> T findTxResource(Class<T> class_, String canonical, String version) { 656 throw new UnsupportedOperationException(Msg.code(2493)); 657 } 658 659 @Override 660 public Boolean subsumes(ValidationOptions optionsArg, Coding parent, Coding child) { 661 throw new UnsupportedOperationException(Msg.code(2488)); 662 } 663 664 @Override 665 public boolean isServerSideSystem(String url) { 666 return false; 667 } 668 669 @Override 670 public OperationOutcome validateTxResource(ValidationOptions options, Resource resource) { 671 throw new UnsupportedOperationException(Msg.code(2734)); 672 } 673}