001package org.hl7.fhir.r5.context; 002 003import java.io.FileNotFoundException; 004import java.io.IOException; 005import java.io.InputStream; 006import java.util.ArrayList; 007import java.util.Collection; 008import java.util.Date; 009 010/* 011 Copyright (c) 2011+, HL7, Inc. 012 All rights reserved. 013 014 Redistribution and use in source and binary forms, with or without modification, 015 are permitted provided that the following conditions are met: 016 017 * Redistributions of source code must retain the above copyright notice, this 018 list of conditions and the following disclaimer. 019 * Redistributions in binary form must reproduce the above copyright notice, 020 this list of conditions and the following disclaimer in the documentation 021 and/or other materials provided with the distribution. 022 * Neither the name of HL7 nor the names of its contributors may be used to 023 endorse or promote products derived from this software without specific 024 prior written permission. 025 026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 027 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 028 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 029 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 030 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 031 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 032 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 033 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 034 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 035 POSSIBILITY OF SUCH DAMAGE. 036 037 */ 038 039 040 041import java.util.List; 042import java.util.Locale; 043import java.util.Map; 044import java.util.Set; 045 046import org.fhir.ucum.UcumService; 047import org.hl7.fhir.exceptions.DefinitionException; 048import org.hl7.fhir.exceptions.FHIRException; 049import org.hl7.fhir.exceptions.TerminologyServiceException; 050import org.hl7.fhir.r5.context.TerminologyCache.CacheToken; 051import org.hl7.fhir.r5.elementmodel.Element; 052import org.hl7.fhir.r5.formats.IParser; 053import org.hl7.fhir.r5.formats.ParserType; 054import org.hl7.fhir.r5.model.Bundle; 055import org.hl7.fhir.r5.model.CanonicalResource; 056import org.hl7.fhir.r5.model.CodeSystem; 057import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; 058import org.hl7.fhir.r5.model.CodeableConcept; 059import org.hl7.fhir.r5.model.Coding; 060import org.hl7.fhir.r5.model.ConceptMap; 061import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; 062import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; 063import org.hl7.fhir.r5.model.NamingSystem; 064import org.hl7.fhir.r5.model.PackageInformation; 065import org.hl7.fhir.r5.model.Parameters; 066import org.hl7.fhir.r5.model.Resource; 067import org.hl7.fhir.r5.model.StructureDefinition; 068import org.hl7.fhir.r5.model.StructureMap; 069import org.hl7.fhir.r5.model.ValueSet; 070import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; 071import org.hl7.fhir.r5.profilemodel.PEDefinition; 072import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy; 073import org.hl7.fhir.r5.profilemodel.PEBuilder; 074import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome; 075import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass; 076import org.hl7.fhir.r5.utils.validation.IResourceValidator; 077import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier; 078import org.hl7.fhir.utilities.TimeTracker; 079import org.hl7.fhir.utilities.TranslationServices; 080import org.hl7.fhir.utilities.npm.BasePackageCacheManager; 081import org.hl7.fhir.utilities.npm.NpmPackage; 082import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation; 083import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; 084import org.hl7.fhir.utilities.validation.ValidationMessage; 085import org.hl7.fhir.utilities.validation.ValidationOptions; 086 087import com.google.gson.JsonSyntaxException; 088 089import javax.annotation.Nonnull; 090 091 092/** 093 * This is the standard interface used for access to underlying FHIR 094 * services through the tools and utilities provided by the reference 095 * implementation. 096 * 097 * The functionality it provides is 098 * - get access to canonical resources,terminology services, and validator 099 * (you can't create a validator directly because it needs access 100 * to the right context for their information) 101 * 102 * - find resources that the tools need to carry out their tasks 103 * 104 * - provide access to terminology services they need. 105 * (typically, these terminology service requests are just 106 * passed through to the local implementation's terminology 107 * service) 108 * 109 * @author Grahame 110 */ 111 112public interface IWorkerContext { 113 114 class ValidationResult { 115 private ConceptDefinitionComponent definition; 116 private String preferredDisplay; 117 private String system; 118 private String version; 119 private IssueSeverity severity; 120 private String message; 121 private TerminologyServiceErrorClass errorClass; 122 private String txLink; 123 private String diagnostics; 124 private List<OperationOutcomeIssueComponent> issues = new ArrayList<>(); 125 private CodeableConcept codeableConcept; 126 private Set<String> unknownSystems; 127 private boolean inactive; 128 private String status; 129 130 @Override 131 public String toString() { 132 return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass=" 133 + errorClass + ", txLink=" + txLink + "]"; 134 } 135 136 public ValidationResult(IssueSeverity severity, String message, List<OperationOutcomeIssueComponent> issues) { 137 this.severity = severity; 138 this.message = message; 139 if (issues != null) { 140 this.issues.addAll(issues); 141 } 142 } 143 144 public ValidationResult(String system, String version, ConceptDefinitionComponent definition, String preferredDisplay) { 145 this.system = system; 146 this.version = version; 147 this.definition = definition; 148 this.preferredDisplay = preferredDisplay; 149 } 150 151 public ValidationResult(IssueSeverity severity, String message, String system, String version, ConceptDefinitionComponent definition, String preferredDisplay, List<OperationOutcomeIssueComponent> issues) { 152 this.severity = severity; 153 this.message = message; 154 this.system = system; 155 this.version = version; 156 this.definition = definition; 157 this.preferredDisplay = preferredDisplay; 158 if (issues != null) { 159 this.issues.addAll(issues); 160 } 161 } 162 163 public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass, List<OperationOutcomeIssueComponent> issues) { 164 this.severity = severity; 165 this.message = message; 166 this.errorClass = errorClass; 167 if (issues != null) { 168 this.issues.addAll(issues); 169 } 170 } 171 172 public boolean isOk() { 173 return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING; 174 } 175 176 public String getSystem() { 177 return system; 178 } 179 180 public String getVersion() { 181 return version; 182 } 183 184 public String getDisplay() { 185 if (preferredDisplay != null) { 186 return preferredDisplay; 187 } else { 188 return definition == null ? null : definition.getDisplay(); 189 } 190 } 191 192 public void setDisplay(String display) { 193 this.preferredDisplay = display; 194 } 195 196 public void setSystem(String system) { 197 this.system = system; 198 } 199 200 public void setVersion(String version) { 201 this.version = version; 202 } 203 204 public String getCode() { 205 return definition == null ? null : definition.getCode(); 206 } 207 208 public String getDefinition() { 209 return definition == null ? null : definition.getDefinition(); 210 } 211 212 public void setDefinition(ConceptDefinitionComponent definition) { 213 this.definition = definition; 214 } 215 216 public ConceptDefinitionComponent asConceptDefinition() { 217 return definition; 218 } 219 220 public IssueSeverity getSeverity() { 221 return severity; 222 } 223 224 public String getMessage() { 225 return message; 226 } 227 228 public boolean IsNoService() { 229 return errorClass == TerminologyServiceErrorClass.NOSERVICE; 230 } 231 232 public TerminologyServiceErrorClass getErrorClass() { 233 return errorClass; 234 } 235 236 public ValidationResult setSeverity(IssueSeverity severity) { 237 this.severity = severity; 238 return this; 239 } 240 241 public ValidationResult setMessage(String message) { 242 this.message = message; 243 return this; 244 } 245 246 public ValidationResult addToMessage(String message) { 247 this.message = this.message == null ? message : this.message +"; "+ message; 248 return this; 249 } 250 251 public ValidationResult setErrorClass(TerminologyServiceErrorClass errorClass) { 252 this.errorClass = errorClass; 253 return this; 254 } 255 256 public String getTxLink() { 257 return txLink; 258 } 259 260 public ValidationResult setTxLink(String txLink) { 261 this.txLink = txLink; 262 return this; 263 } 264 265 public boolean hasMessage() { 266 return message != null; 267 } 268 269 public String getDiagnostics() { 270 return diagnostics; 271 } 272 273 public void setDiagnostics(String diagnostics) { 274 this.diagnostics = diagnostics; 275 } 276 277 public Coding asCoding() { 278 if (isOk() && definition != null && definition.getCode() != null) { 279 return new Coding(system, definition.getCode(), definition.getDisplay()); 280 } else { 281 return null; 282 } 283 } 284 285 public List<OperationOutcomeIssueComponent> getIssues() { 286 return issues; 287 } 288 289 public ValidationResult addCodeableConcept(CodeableConcept vcc) { 290 if (!vcc.isEmpty()) { 291 codeableConcept = vcc; 292 } 293 return this; 294 } 295 296 public CodeableConcept getCodeableConcept() { 297 return codeableConcept; 298 } 299 300 public Set<String> getUnknownSystems() { 301 return unknownSystems; 302 } 303 304 public ValidationResult setUnknownSystems(Set<String> unknownSystems) { 305 this.unknownSystems = unknownSystems; 306 return this; 307 } 308 309 public String unknownSystems() { 310 if (unknownSystems == null) { 311 return null; 312 } 313 if (unknownSystems.size() == 1) { 314 return unknownSystems.iterator().next(); 315 } else { 316 return String.join(",", unknownSystems); 317 } 318 } 319 320 public void setIssues(List<OperationOutcomeIssueComponent> issues) { 321 if (this.issues != null) { 322 issues.addAll(this.issues); 323 } 324 this.issues = issues; 325 326 } 327 328 public void trimPath(String prefix) { 329 if (issues != null) { 330 for (OperationOutcomeIssueComponent iss : issues) { 331 for (int i = iss.getLocation().size() -1; i >= 0; i--) { 332 var s = iss.getLocation().get(i).primitiveValue(); 333 if (prefix.equals(s)) { 334 iss.getLocation().remove(i); 335 } else if (s.startsWith(prefix+".")) { 336 iss.getLocation().get(i).setValueAsString(s.substring(prefix.length()+1)); 337 } 338 } 339 } 340 } 341 342 } 343 344 public boolean isInactive() { 345 return inactive; 346 } 347 348 public String getStatus() { 349 return status; 350 } 351 352 public ValidationResult setStatus(boolean inactive, String status) { 353 this.inactive = inactive; 354 if (!"inactive".equals(status)) { 355 this.status = status; 356 } 357 return this; 358 } 359 360 } 361 362 public class CodingValidationRequest { 363 private Coding coding; 364 private ValidationResult result; 365 private CacheToken cacheToken; 366 private String vs; 367 368 public CodingValidationRequest(Coding coding) { 369 super(); 370 this.coding = coding; 371 } 372 373 public CodingValidationRequest(Coding coding, String vs) { 374 super(); 375 this.coding = coding; 376 this.vs = vs; 377 } 378 379 public String getVs() { 380 return vs; 381 } 382 383 public ValidationResult getResult() { 384 return result; 385 } 386 387 public void setResult(ValidationResult result) { 388 this.result = result; 389 } 390 391 public Coding getCoding() { 392 return coding; 393 } 394 395 public boolean hasResult() { 396 return result != null; 397 } 398 399 /** 400 * internal logic; external users of batch validation should ignore this property 401 * 402 * @return 403 */ 404 public CacheToken getCacheToken() { 405 return cacheToken; 406 } 407 408 /** 409 * internal logic; external users of batch validation should ignore this property 410 * 411 * @param cacheToken 412 */ 413 public void setCacheToken(CacheToken cacheToken) { 414 this.cacheToken = cacheToken; 415 } 416 417 418 } 419 420 421 public interface IContextResourceLoader { 422 /** 423 * @return List of the resource types that should be loaded 424 */ 425 List<String> getTypes(); 426 427 /** 428 * Request to actually load the resources and do whatever is required 429 * 430 * @param stream 431 * @param isJson 432 * @return A bundle because some single resources become multiple resources after loading 433 * @throws FHIRException 434 * @throws IOException 435 */ 436 Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException; 437 438 /** 439 * Load a single resources (lazy load) 440 * 441 * @param stream 442 * @param isJson 443 * @return 444 * @throws FHIRException - throw this if you a single resource can't be returned - can't lazy load in this circumstance 445 * @throws IOException 446 */ 447 Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException; 448 449 /** 450 * get the path for references to this resource. 451 * @param resource 452 * @return null if not tracking paths 453 */ 454 String getResourcePath(Resource resource); 455 456 /** 457 * called when a new package is being loaded 458 * 459 * this is called by loadPackageAndDependencies when a new package is loaded 460 * @param npm 461 * @return 462 * @throws IOException 463 * @throws JsonSyntaxException 464 */ 465 IContextResourceLoader getNewLoader(NpmPackage npm) throws JsonSyntaxException, IOException; 466 467 /** 468 * called when processing R2 for implicit code systems in ValueSets 469 * 470 * @return 471 */ 472 List<CodeSystem> getCodeSystems(); 473 474 /** 475 * if this is true, then the loader will patch canonical URLs and cross-links 476 * to add /X.X/ into the URL so that different versions can be loaded safely 477 * 478 * default is false 479 */ 480 void setPatchUrls(boolean value); 481 482 /** 483 * patch the URL if necessary 484 * 485 * @param url 486 * @return 487 */ 488 String patchUrl(String url, String resourceType); 489 490 /** 491 * set this to false (default is true) if you don't want profiles loaded 492 * @param value 493 * @return 494 */ 495 IContextResourceLoader setLoadProfiles(boolean value); 496 497 /** 498 * Called during the loading process - the loader can decide which resources to load. 499 * At this point, only the .index.json is being read 500 * 501 * @param pi 502 * @param pri 503 * @return 504 */ 505 boolean wantLoad(NpmPackage pi, PackageResourceInformation pri); 506 } 507 508 /** 509 * Get the version of the definitions loaded in context 510 * This *does not* have to be 5.0 (R5) - the context can load other versions 511 * 512 * @return 513 */ 514 public String getVersion(); 515 516 /** 517 * Get the UCUM service that provides access to units of measure reasoning services 518 * 519 * This service might not be available 520 * 521 * @return 522 */ 523 public UcumService getUcumService(); 524 public void setUcumService(UcumService ucumService); 525 526 /** 527 * Get a validator that can check whether a resource is valid 528 * 529 * @return a prepared generator 530 * @throws FHIRException 531 * @ 532 */ 533 public IResourceValidator newValidator() throws FHIRException; 534 535 // -- resource fetchers --------------------------------------------------- 536 537 /** 538 * Find an identified resource. The most common use of this is to access the the 539 * standard conformance resources that are part of the standard - structure 540 * definitions, value sets, concept maps, etc. 541 * 542 * Also, the narrative generator uses this, and may access any kind of resource 543 * 544 * The URI is called speculatively for things that might exist, so not finding 545 * a matching resource, return null, not an error 546 * 547 * The URI can have one of 3 formats: 548 * - a full URL e.g. http://acme.org/fhir/ValueSet/[id] 549 * - a relative URL e.g. ValueSet/[id] 550 * - a logical id e.g. [id] 551 * 552 * It's an error if the second form doesn't agree with class_. It's an 553 * error if class_ is null for the last form 554 * 555 * class can be Resource, DomainResource or CanonicalResource, which means resource of all kinds 556 * 557 * @param resource 558 * @param Reference 559 * @return 560 * @throws FHIRException 561 * @throws Exception 562 */ 563 public <T extends Resource> T fetchResource(Class<T> class_, String uri); 564 public <T extends Resource> T fetchResourceRaw(Class<T> class_, String uri); 565 public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException; 566 public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceOfReference) throws FHIRException; 567 public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version); 568 569 /** has the same functionality as fetchResource, but passes in information about the source of the 570 * reference (this may affect resolution of version) 571 * 572 * @param <T> 573 * @param class_ 574 * @param uri 575 * @param canonicalForSource 576 * @return 577 */ 578 public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource sourceOfReference); 579 580 /** 581 * Fetch all the resources of a particular type. if class == (null | Resource | DomainResource | CanonicalResource) return everything 582 * 583 * @param <T> 584 * @param class_ 585 * @param uri 586 * @param canonicalForSource 587 * @return 588 */ 589 public <T extends Resource> List<T> fetchResourcesByType(Class<T> class_); 590 591 /** 592 * Variation of fetchResource when you have a string type, and don't need the right class 593 * 594 * The URI can have one of 3 formats: 595 * - a full URL e.g. http://acme.org/fhir/ValueSet/[id] 596 * - a relative URL e.g. ValueSet/[id] 597 * - a logical id e.g. [id] 598 * 599 * if type == null, the URI can't be a simple logical id 600 * 601 * @param type 602 * @param uri 603 * @return 604 */ 605 public Resource fetchResourceById(String type, String uri); 606 607 /** 608 * find whether a resource is available. 609 * 610 * Implementations of the interface can assume that if hasResource ruturns 611 * true, the resource will usually be fetched subsequently 612 * 613 * @param class_ 614 * @param uri 615 * @return 616 */ 617 public <T extends Resource> boolean hasResource(Class<T> class_, String uri); 618 619 /** 620 * cache a resource for later retrieval using fetchResource. 621 * 622 * Note that various context implementations will have their own ways of loading 623 * rseources, and not all need implement cacheResource. 624 * 625 * If the resource is loaded out of a package, call cacheResourceFromPackage instead 626 * @param res 627 * @throws FHIRException 628 */ 629 public void cacheResource(Resource res) throws FHIRException; 630 631 /** 632 * cache a resource for later retrieval using fetchResource. 633 * 634 * The package information is used to help manage the cache internally, and to 635 * help with reference resolution. Packages should be define using cachePackage (but don't have to be) 636 * 637 * Note that various context implementations will have their own ways of loading 638 * rseources, and not all need implement cacheResource 639 * 640 * @param res 641 * @throws FHIRException 642 */ 643 public void cacheResourceFromPackage(Resource res, PackageInformation packageInfo) throws FHIRException; 644 645 /** 646 * Inform the cache about package dependencies. This can be used to help resolve references 647 * 648 * Note that the cache doesn't load dependencies 649 * 650 * @param packageInfo 651 */ 652 public void cachePackage(PackageInformation packageInfo); 653 654 // -- profile services --------------------------------------------------------- 655 656 /** 657 * @return a list of the resource names defined for this version 658 */ 659 public List<String> getResourceNames(); 660 /** 661 * @return a set of the resource names defined for this version 662 */ 663 public Set<String> getResourceNamesAsSet(); 664 665 // -- Terminology services ------------------------------------------------------ 666 667 /** 668 * Set the expansion parameters passed through the terminology server when txServer calls are made 669 * 670 * Note that the Validation Options override these when they are specified on validateCode 671 */ 672 public Parameters getExpansionParameters(); 673 674 /** 675 * Get the expansion parameters passed through the terminology server when txServer calls are made 676 * 677 * Note that the Validation Options override these when they are specified on validateCode 678 */ 679 public void setExpansionProfile(Parameters expParameters); 680 681 // these are the terminology services used internally by the tools 682 /** 683 * Find the code system definition for the nominated system uri. 684 * return null if there isn't one (then the tool might try 685 * supportsSystem) 686 * 687 * This is a short cut for fetchResource(CodeSystem.class...) 688 * 689 * @param system 690 * @return 691 */ 692 public CodeSystem fetchCodeSystem(String system); 693 public CodeSystem fetchCodeSystem(String system, String version); 694 695 /** 696 * Like fetchCodeSystem, except that the context will find any CodeSysetm supplements and merge them into the 697 * @param system 698 * @return 699 */ 700 public CodeSystem fetchSupplementedCodeSystem(String system); 701 public CodeSystem fetchSupplementedCodeSystem(String system, String version); 702 703 /** 704 * True if the underlying terminology service provider will do 705 * expansion and code validation for the terminology. Corresponds 706 * to the extension 707 * 708 * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system 709 * 710 * in the Conformance resource 711 * 712 * Not that not all supported code systems have an available CodeSystem resource 713 * 714 * @param system 715 * @return 716 * @throws Exception 717 */ 718 public boolean supportsSystem(String system) throws TerminologyServiceException; 719 720 /** 721 * ValueSet Expansion - see $expand 722 * 723 * @param source 724 * @return 725 */ 726 public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical); 727 728 /** 729 * ValueSet Expansion - see $expand 730 * 731 * @param source 732 * @return 733 */ 734 public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk); 735 736 /** 737 * ValueSet Expansion - see $expand, but resolves the binding first 738 * 739 * @param source 740 * @return 741 * @throws FHIRException 742 */ 743 public ValueSetExpansionOutcome expandVS(Resource src, ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) throws FHIRException; 744 745 /** 746 * Value set expanion inside the internal expansion engine - used 747 * for references to supported system (see "supportsSystem") for 748 * which there is no value set. 749 * 750 * @param inc 751 * @return 752 * @throws FHIRException 753 */ 754 ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean hierarchical, boolean noInactive) throws TerminologyServiceException; 755 756 /** 757 * get/set the locale used when creating messages 758 * 759 * todo: what's the difference? 760 * 761 * @return 762 */ 763 Locale getLocale(); 764 void setLocale(Locale locale); 765 void setValidationMessageLanguage(Locale locale); 766 767 /** 768 * Access to the contexts internationalised error messages 769 * 770 * @param theMessage 771 * @param theMessageArguments 772 * @return 773 */ 774 String formatMessage(String theMessage, Object... theMessageArguments); 775 String formatMessagePlural(Integer pluralNum, String theMessage, Object... theMessageArguments); 776 777 /** 778 * Validation of a code - consult the terminology infrstructure and/or service 779 * to see whether it is known. If known, return a description of it 780 * 781 * note: always return a result, with either an error or a code description 782 * 783 * corresponds to 2 terminology service calls: $validate-code and $lookup 784 * 785 * in this case, the system will be inferred from the value set. It's an error to call this one without the value set 786 * 787 * @param options - validation options (required) 788 * @param code he code to validate (required) 789 * @param vs the applicable valueset (required) 790 * @return 791 */ 792 public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs); 793 794 /** 795 * Validation of a code - consult the terminology infrstructure and/or service 796 * to see whether it is known. If known, return a description of it 797 * 798 * note: always return a result, with either an error or a code description 799 * 800 * corresponds to 2 terminology service calls: $validate-code and $lookup 801 * 802 * @param options - validation options (required) 803 * @param system - equals Coding.system (required) 804 * @param code - equals Coding.code (required) 805 * @param display - equals Coding.display (optional) 806 * @return 807 */ 808 public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display); 809 810 /** 811 * Validation of a code - consult the terminology infrstructure and/or service 812 * to see whether it is known. If known, return a description of it 813 * 814 * note: always return a result, with either an error or a code description 815 * 816 * corresponds to 2 terminology service calls: $validate-code and $lookup 817 * 818 * @param options - validation options (required) 819 * @param system - equals Coding.system (required) 820 * @param code - equals Coding.code (required) 821 * @param display - equals Coding.display (optional) 822 * @param vs the applicable valueset (optional) 823 * @return 824 */ 825 public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display, ValueSet vs); 826 827 /** 828 * Validation of a code - consult the terminology infrstructure and/or service 829 * to see whether it is known. If known, return a description of it 830 * 831 * note: always return a result, with either an error or a code description 832 * 833 * corresponds to 2 terminology service calls: $validate-code and $lookup 834 * 835 * Note that this doesn't validate binding strength (e.g. is just text allowed?) 836 * 837 * @param options - validation options (required) 838 * @param code - CodeableConcept to validate 839 * @param vs the applicable valueset (optional) 840 * @return 841 */ 842 public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs); 843 844 /** 845 * Validation of a code - consult the terminology infrstructure and/or service 846 * to see whether it is known. If known, return a description of it 847 * 848 * note: always return a result, with either an error or a code description 849 * 850 * corresponds to 2 terminology service calls: $validate-code and $lookup 851 * 852 * in this case, the system will be inferred from the value set. It's an error to call this one without the value set 853 * 854 * @param options - validation options (required) 855 * @param code - Coding to validate 856 * @param vs the applicable valueset (optional) 857 * @return 858 */ 859 public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs); 860 861 /** 862 * See comments in ValidationContextCarrier. This is called when there might be additional value sets etc 863 * available in the context, but we don't want to pre-process them. 864 * 865 * @param options 866 * @param code 867 * @param vs 868 * @param ctxt 869 * @return 870 */ 871 public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt); 872 873 /** 874 * Batch validate code - reduce latency and do a bunch of codes in a single server call. 875 * Each is the same as a validateCode 876 * 877 * @param options 878 * @param codes 879 * @param vs 880 */ 881 public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs); 882 public void validateCodeBatchByRef(ValidationOptions options, List<? extends CodingValidationRequest> codes, String vsUrl); 883 884 885 // todo: figure these out 886 public Map<String, NamingSystem> getNSUrlMap(); 887 public TranslationServices translator(); 888 889 public interface ILoggingService { 890 public enum LogCategory { 891 INIT, 892 PROGRESS, 893 TX, 894 CONTEXT, 895 GENERATE, 896 HTML 897 } 898 public void logMessage(String message); // status messages, always display 899 public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging 900 public boolean isDebugLogging(); // whether to log debug information 901 } 902 public void setLogger(@Nonnull ILoggingService logger); 903 public ILoggingService getLogger(); 904 905 public boolean isNoTerminologyServer(); 906 public Set<String> getCodeSystemsUsed(); 907 public int getClientRetryCount(); 908 public IWorkerContext setClientRetryCount(int value); 909 910 public TimeTracker clock(); 911 912 /** 913 * This is a short cut for fetchResource(StructureDefinition.class, ...) 914 * but it accepts a typename - that is, it resolves based on StructureDefinition.type 915 * or StructureDefinition.url. This only resolves to http://hl7.org/fhir/StructureDefinition/{typename} 916 * 917 * @param typeName 918 * @return 919 */ 920 public StructureDefinition fetchTypeDefinition(String typeName); 921 922 /** 923 * This finds all the structure definitions that have the given typeName 924 * 925 * @param typeName 926 * @return 927 */ 928 public List<StructureDefinition> fetchTypeDefinitions(String n); 929 930 931 /** 932 * Returns a set of keys that can be used to get binaries from this context. 933 * The binaries come from the loaded packages (mostly the pubpack) 934 * 935 * @return a set of binaries or null 936 */ 937 public Set<String> getBinaryKeysAsSet(); 938 939 /** 940 * Returns true if this worker context contains a binary for this key. 941 * 942 * @param binaryKey 943 * @return true if binary is available for this key 944 */ 945 public boolean hasBinaryKey(String binaryKey); 946 947 /** 948 * Returns the binary for the key 949 * @param binaryKey 950 * @return 951 */ 952 public byte[] getBinaryForKey(String binaryKey); 953 954 /* 955 * Todo: move these loaders out to IWorkerContextManager 956 * 957 */ 958 /** 959 * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package 960 * 961 * note that the package system uses lazy loading; the loader will be called later when the classes that use the context need the relevant resource 962 * 963 * @param pi - the package to load 964 * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version). 965 * @return the number of resources loaded 966 */ 967 int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException; 968 969 /** 970 * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package 971 * 972 * note that the package system uses lazy loading; the loader will be called later when the classes that use the context need the relevant resource 973 * 974 * Deprecated - use the simpler method where the types come from the loader. 975 * 976 * @param pi - the package to load 977 * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version). 978 * @param types - which types of resources to load 979 * @return the number of resources loaded 980 */ 981 @Deprecated 982 int loadFromPackage(NpmPackage pi, IContextResourceLoader loader, List<String> types) throws FileNotFoundException, IOException, FHIRException; 983 984 /** 985 * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package 986 * 987 * note that the package system uses lazy loading; the loader will be called later when the classes that use the context need the relevant resource 988 * 989 * This method also loads all the packages that the package depends on (recursively) 990 * 991 * @param pi - the package to load 992 * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version). 993 * @param pcm - used to find and load additional dependencies 994 * @return the number of resources loaded 995 */ 996 int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException; 997 998 public boolean hasPackage(String id, String ver); 999 public boolean hasPackage(PackageInformation pack); 1000 public PackageInformation getPackage(String id, String ver); 1001 public PackageInformation getPackageForUrl(String url); 1002 1003 public IWorkerContextManager.IPackageLoadingTracker getPackageTracker(); 1004 public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker); 1005 1006 public String getSpecUrl(); 1007 1008 public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps, boolean fixedProps); 1009 1010 public boolean isForPublication(); 1011 public void setForPublication(boolean value); 1012}