001package org.hl7.fhir.r5.context;
002
003import java.io.FileNotFoundException;
004import java.io.IOException;
005import java.util.ArrayList;
006import java.util.Collection;
007import java.util.Collections;
008import java.util.Comparator;
009import java.util.Date;
010import java.util.HashSet;
011
012/*
013  Copyright (c) 2011+, HL7, Inc.
014  All rights reserved.
015
016  Redistribution and use in source and binary forms, with or without modification, 
017  are permitted provided that the following conditions are met:
018
019 * Redistributions of source code must retain the above copyright notice, this 
020     list of conditions and the following disclaimer.
021 * Redistributions in binary form must reproduce the above copyright notice, 
022     this list of conditions and the following disclaimer in the documentation 
023     and/or other materials provided with the distribution.
024 * Neither the name of HL7 nor the names of its contributors may be used to 
025     endorse or promote products derived from this software without specific 
026     prior written permission.
027
028  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
029  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
030  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
031  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
032  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
033  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
034  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
035  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
036  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
037  POSSIBILITY OF SUCH DAMAGE.
038
039 */
040
041
042
043import java.util.List;
044import java.util.Locale;
045import java.util.Map;
046import java.util.Set;
047
048import lombok.Getter;
049import org.fhir.ucum.UcumService;
050import org.hl7.fhir.exceptions.DefinitionException;
051import org.hl7.fhir.exceptions.FHIRException;
052import org.hl7.fhir.exceptions.TerminologyServiceException;
053import org.hl7.fhir.r5.context.IWorkerContext.OIDDefinition;
054import org.hl7.fhir.r5.context.IWorkerContext.OIDDefinitionComparer;
055import org.hl7.fhir.r5.context.IWorkerContext.ITerminologyOperationDetails;
056import org.hl7.fhir.r5.elementmodel.Element;
057import org.hl7.fhir.r5.formats.IParser;
058import org.hl7.fhir.r5.formats.ParserType;
059import org.hl7.fhir.r5.model.CanonicalResource;
060import org.hl7.fhir.r5.model.CodeSystem;
061import org.hl7.fhir.r5.model.CodeableConcept;
062import org.hl7.fhir.r5.model.Coding;
063import org.hl7.fhir.r5.model.ConceptMap;
064import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
065import org.hl7.fhir.r5.model.NamingSystem;
066import org.hl7.fhir.r5.model.OperationOutcome;
067import org.hl7.fhir.r5.model.PackageInformation;
068import org.hl7.fhir.r5.model.Parameters;
069import org.hl7.fhir.r5.model.Resource;
070import org.hl7.fhir.r5.model.StructureDefinition;
071import org.hl7.fhir.r5.model.StructureMap;
072import org.hl7.fhir.r5.model.ValueSet;
073import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
074import org.hl7.fhir.r5.profilemodel.PEDefinition;
075import org.hl7.fhir.r5.profilemodel.PEBuilder.PEElementPropertiesPolicy;
076import org.hl7.fhir.r5.profilemodel.PEBuilder;
077import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
078import org.hl7.fhir.r5.terminologies.utilities.CodingValidationRequest;
079import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
080import org.hl7.fhir.r5.utils.validation.IResourceValidator;
081import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
082import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
083import org.hl7.fhir.utilities.FhirPublication;
084import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
085import org.hl7.fhir.utilities.TimeTracker;
086import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
087import org.hl7.fhir.utilities.npm.NpmPackage;
088import org.hl7.fhir.utilities.validation.ValidationMessage;
089import org.hl7.fhir.utilities.validation.ValidationOptions;
090
091import javax.annotation.Nonnull;
092
093
094/**
095 * This is the standard interface used for access to underlying FHIR
096 * services through the tools and utilities provided by the reference
097 * implementation. 
098 * 
099 * The functionality it provides is 
100 *  - get access to canonical resources,terminology services, and validator
101 *    (you can't create a validator directly because it needs access 
102 *    to the right context for their information)
103 *    
104 *  - find resources that the tools need to carry out their tasks
105 *  
106 *  - provide access to terminology services they need. 
107 *    (typically, these terminology service requests are just
108 *    passed through to the local implementation's terminology
109 *    service)    
110 *  
111 * @author Grahame
112 */
113
114@MarkedToMoveToAdjunctPackage
115public interface IWorkerContext {
116
117  public interface ITerminologyOperationDetails {
118
119    public void seeSupplement(CodeSystem supp);
120  }
121  public class OIDDefinitionComparer implements Comparator<OIDDefinition> {
122
123    @Override
124    public int compare(OIDDefinition o1, OIDDefinition o2) {
125      if (o1.getUrl().equals(o2.getUrl())) {
126        return -o1.getVersion().compareTo(o2.getVersion());        
127      } else {
128        return o1.getUrl().compareTo(o2.getUrl());
129      }
130    }
131  }
132
133  public class OIDDefinition {
134    private String type;
135    private String oid;
136    private String url;
137    private String version;
138    private String packageSrc;
139    private String status;
140    protected OIDDefinition(String type, String oid, String url, String version, String status, String packageSrc) {
141      super();
142      this.type = type;
143      this.oid = oid;
144      this.url = url;
145      this.version = version == null ? "" : version;
146      this.packageSrc = packageSrc;
147      this.status = status;
148    }
149    public String getType() {
150      return type;
151    }
152    public String getOid() {
153      return oid;
154    }
155    public String getUrl() {
156      return url;
157    }
158    public String getVersion() {
159      return version;
160    }
161    public String getStatus() {
162      return status;
163    }
164    public String getPackageSrc() {
165      return packageSrc;
166    }
167    public String summary() {
168      return url+(version == null ? "" : "|"+version)+(packageSrc != null ? "("+packageSrc+")" : "");
169    }
170    public boolean matches(OIDDefinition t) {
171      return url.equals(t.url) && version.equals(t.version);
172    }
173    
174  }
175
176  public class OIDSummary {
177    private List<OIDDefinition> definitions = new ArrayList<>();
178    private List<String> urls = new ArrayList<>();
179
180    public void addOID(OIDDefinition d) {
181      for (OIDDefinition t : definitions) {
182        if (d.matches(t)) {
183          return;
184        }
185      }
186      definitions.add(d);
187      if (!urls.contains(d.getUrl())) {
188        urls.add(d.getUrl());
189      }
190    }
191    
192    public void addOIDs(Collection<OIDDefinition> collection) {
193      for (OIDDefinition t : collection) {
194        addOID(t);
195      }
196    }
197    
198    public List<OIDDefinition> getDefinitions() {
199      return definitions;
200    }
201
202    public void sort() {
203      Collections.sort(definitions, new OIDDefinitionComparer());
204      Collections.sort(urls);
205    }
206    public String describe() {
207      CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
208      for (OIDDefinition d : definitions) {
209        b.append(d.summary());
210      }
211      return b.toString();
212    }
213
214    public String chooseBestUrl() {
215      for (OIDDefinition d : definitions) {
216        if (d.getPackageSrc() == null) {
217          return d.getUrl();
218        }
219      }
220      for (OIDDefinition d : definitions) {
221        if (d.getUrl().startsWith("http://hl7.org/fhir/")) {
222          return d.getUrl();
223        }
224      }
225      for (OIDDefinition d : definitions) {
226        if (!d.getUrl().contains("vsac")) {
227          return d.getUrl();
228        }
229      }
230      return null;
231    }
232
233    public int urlCount() {
234      return urls.size();
235    }
236
237    public String getUrl() {
238      return urls.iterator().next();
239    }
240  }
241  /**
242   * Get the version of the base definitions loaded in context
243   * This *does not* have to be 5.0 (R5) - the context can load other versions
244   * 
245   * Note that more than one version might be loaded at once, but one version is always the default / master
246   * 
247   * @return
248   */
249  public String getVersion();
250
251  /**
252   * Get the UCUM service that provides access to units of measure reasoning services 
253   * 
254   * This service might not be available 
255   * 
256   * @return
257   */
258  public UcumService getUcumService();
259  public void setUcumService(UcumService ucumService);
260
261  /**
262   * Get a validator that can check whether a resource is valid 
263   * 
264   * @return a prepared generator
265   * @throws FHIRException 
266   * @
267   */
268  public IResourceValidator newValidator() throws FHIRException;
269
270  // -- resource fetchers ---------------------------------------------------
271
272  /**
273   * Find an identified resource. The most common use of this is to access the the 
274   * standard conformance resources that are part of the standard - structure 
275   * definitions, value sets, concept maps, etc.
276   * 
277   * Also, the narrative generator uses this, and may access any kind of resource
278   * 
279   * The URI is called speculatively for things that might exist, so not finding 
280   * a matching resource, return null, not an error
281   * 
282   * The URI can have one of 3 formats:
283   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
284   *  - a relative URL e.g. ValueSet/[id]
285   *  - a logical id e.g. [id]
286   *  
287   * It's an error if the second form doesn't agree with class_. It's an 
288   * error if class_ is null for the last form
289   * 
290   * class can be Resource, DomainResource or CanonicalResource, which means resource of all kinds
291   * 
292   * @param resource
293   * @param Reference
294   * @return
295   * @throws FHIRException 
296   * @throws Exception
297   */
298  public <T extends Resource> T fetchResource(Class<T> class_, String uri);
299  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
300  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceOfReference) throws FHIRException;
301  public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version);
302  public <T extends Resource> T fetchResource(Class<T> class_, String uri, FhirPublication fhirVersion);
303  public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version, FhirPublication fhirVersion);
304
305  /**
306   * Find an identified resource, but do not do any processing on it.
307   * The usual processing that happens is ensuring that the snapshot is
308   * generated before returning it; This routine is used in the snapshot
309   * generation routines to avoid circular dependency challenges generating
310   * snapshots.
311   *
312   * class can be Resource, DomainResource or CanonicalResource, which means resource of all kinds
313   *
314   * @param class_
315   * @param uri
316   * @return
317   * @throws FHIRException
318   * @throws Exception
319   */
320  public <T extends Resource> T fetchResourceRaw(Class<T> class_, String uri);
321
322
323  /** has the same functionality as fetchResource, but passes in information about the source of the
324   * reference (this may affect resolution of version)
325   *  
326   * @param <T>
327   * @param class_
328   * @param uri
329   * @param canonicalForSource
330   * @return
331   */
332  public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource sourceOfReference);
333
334  /** 
335   * Fetch all the resources of a particular type. if class == (null | Resource | DomainResource | CanonicalResource) return everything
336   *  
337   * @param <T>
338   * @param class_
339   * @param uri
340   * @param canonicalForSource
341   * @return
342   */
343  public <T extends Resource> List<T> fetchResourcesByType(Class<T> class_);
344  public <T extends Resource> List<T> fetchResourceVersionsByTypeAndUrl(Class<T> class_, String url);
345  @Deprecated
346  public <T extends Resource> List<T> fetchResourcesByType(Class<T> class_, FhirPublication fhirVersion);
347
348
349  /**
350   * Fetch all the resources for the given URL - all matching versions
351   * 
352   * @param url
353   * @return
354   */
355  public <T extends Resource> List<T> fetchResourcesByUrl(Class<T> class_, String url);
356  
357  /**
358   * Variation of fetchResource when you have a string type, and don't need the right class
359   * 
360   * The URI can have one of 3 formats:
361   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
362   *  - a relative URL e.g. ValueSet/[id]
363   *  - a logical id e.g. [id]
364   *  
365   * if type == null, the URI can't be a simple logical id
366   * 
367   * @param type
368   * @param uri
369   * @return
370   */
371  public Resource fetchResourceById(String type, String uri);
372  public Resource fetchResourceById(String type, String uri, FhirPublication fhirVersion);
373
374  /**
375   * find whether a resource is available. 
376   * 
377   * Implementations of the interface can assume that if hasResource ruturns 
378   * true, the resource will usually be fetched subsequently
379   * 
380   * @param class_
381   * @param uri
382   * @return
383   */
384  public <T extends Resource> boolean hasResource(Class<T> class_, String uri);
385  public <T extends Resource> boolean hasResource(Class<T> class_, String uri, Resource sourceOfReference);
386  public <T extends Resource> boolean hasResource(Class<T> class_, String uri, String fhirVersion);
387
388  /**
389   * cache a resource for later retrieval using fetchResource.
390   * 
391   * Note that various context implementations will have their own ways of loading
392   * rseources, and not all need implement cacheResource.
393   * 
394   * If the resource is loaded out of a package, call cacheResourceFromPackage instead
395   * @param res
396   * @throws FHIRException 
397   */
398  public void cacheResource(Resource res) throws FHIRException;
399
400  /**
401   * cache a resource for later retrieval using fetchResource.
402   * 
403   * The package information is used to help manage the cache internally, and to 
404   * help with reference resolution. Packages should be define using cachePackage (but don't have to be)
405   *    
406   * Note that various context implementations will have their own ways of loading
407   * rseources, and not all need implement cacheResource
408   * 
409   * @param res
410   * @throws FHIRException 
411   */
412  public void cacheResourceFromPackage(Resource res, PackageInformation packageInfo) throws FHIRException;
413
414  /**
415   * Inform the cache about package dependencies. This can be used to help resolve references
416   * 
417   * Note that the cache doesn't load dependencies
418   *  
419   * @param packageInfo
420   */
421  public void cachePackage(PackageInformation packageInfo);
422
423  // -- profile services ---------------------------------------------------------
424
425  /**
426   * @return a list of the resource names defined for this version
427   */
428  public List<String> getResourceNames();
429  public List<String> getResourceNames(FhirPublication fhirVersion);
430  /**
431   * @return a set of the resource names defined for this version
432   */
433  public Set<String> getResourceNamesAsSet();
434  public Set<String> getResourceNamesAsSet(FhirPublication fhirVersion);
435
436  // -- Terminology services ------------------------------------------------------
437
438  /**
439   * Set the expansion parameters passed through the terminology server when txServer calls are made
440   * 
441   * Note that the Validation Options override these when they are specified on validateCode
442   */
443  public Parameters getExpansionParameters();
444
445  /**
446   * Get the expansion parameters passed through the terminology server when txServer calls are made
447   * 
448   * Note that the Validation Options override these when they are specified on validateCode
449   */
450  public void setExpansionParameters(Parameters expParameters);
451
452  // these are the terminology services used internally by the tools
453  /**
454   * Find the code system definition for the nominated system uri. 
455   * return null if there isn't one (then the tool might try 
456   * supportsSystem)
457   * 
458   * This is a short cut for fetchResource(CodeSystem.class...)
459   * 
460   * @param system
461   * @return
462   */
463  public CodeSystem fetchCodeSystem(String system);
464  public CodeSystem fetchCodeSystem(String system, String version);
465  public CodeSystem fetchCodeSystem(String system, FhirPublication fhirVersion);
466  public CodeSystem fetchCodeSystem(String system, String version, FhirPublication fhirVersion);
467
468  /**
469   * Like fetchCodeSystem, except that the context will find any CodeSysetm supplements and merge them into the
470   * @param system
471   * @return
472   */
473  public CodeSystem fetchSupplementedCodeSystem(String system);
474  public CodeSystem fetchSupplementedCodeSystem(String system, String version);
475  public CodeSystem fetchSupplementedCodeSystem(String system, FhirPublication fhirVersion);
476  public CodeSystem fetchSupplementedCodeSystem(String system, String version, FhirPublication fhirVersion);
477
478  /**
479   * True if the underlying terminology service provider will do 
480   * expansion and code validation for the terminology. Corresponds
481   * to the extension 
482   * 
483   * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system
484   * 
485   * in the Conformance resource
486   * 
487   * Not that not all supported code systems have an available CodeSystem resource
488   * 
489   * @param system
490   * @return
491   * @throws Exception 
492   */
493  @Deprecated
494  public boolean supportsSystem(String system) throws TerminologyServiceException;
495  @Deprecated
496  public boolean supportsSystem(String system, FhirPublication fhirVersion) throws TerminologyServiceException;
497
498  /**
499   * return the System Support Information for the server that serves the specified code system
500   * @param system
501   * @param version
502   * @return
503   */
504  public SystemSupportInformation getTxSupportInfo(String system, String version);
505  public SystemSupportInformation getTxSupportInfo(String system);
506
507  /**
508   * ValueSet Expansion - see $expand
509   *  
510   * @param source
511   * @return
512   */
513  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
514
515  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, int count);
516
517  /**
518   * ValueSet Expansion - see $expand
519   *  
520   * @param source
521   * @return
522   */
523  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk);
524
525  public ValueSetExpansionOutcome expandVS(String uri, boolean cacheOk, boolean heiarchical, int count); // set to 0 to just check existence
526  
527  /**
528   * ValueSet Expansion - see $expand, but resolves the binding first
529   *  
530   * @param source
531   * @return
532   * @throws FHIRException 
533   */
534  public ValueSetExpansionOutcome expandVS(Resource src, ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) throws FHIRException;
535
536  /**
537   * Value set expanion inside the internal expansion engine - used 
538   * for references to supported system (see "supportsSystem") for
539   * which there is no value set. 
540   * 
541   * @param inc
542   * @return
543   * @throws FHIRException 
544   */
545  ValueSetExpansionOutcome expandVS(ITerminologyOperationDetails opCtxt, ConceptSetComponent inc, boolean hierarchical, boolean noInactive) throws TerminologyServiceException;
546
547  /**
548   * get/set the locale used when creating messages
549   * 
550   * todo: what's the difference?
551   * 
552   * @return
553   */
554  Locale getLocale();
555
556  /**
557   * Sets the locale for this worker context.
558   *
559   * @param locale The locale to use.
560   * @deprecated Usage of this method is discouraged outside very specific scenarios in testing and the IG publisher.
561   * It is preferred to set the locale via the constructor of the implementing class.
562   */
563  @Deprecated
564  void setLocale(Locale locale);
565
566  @Deprecated
567  void setValidationMessageLanguage(Locale locale);
568
569  /**
570   * Access to the contexts internationalised error messages
571   * 
572   * For rendering internationalization, see RenderingContext
573   *  
574   * @param theMessage
575   * @param theMessageArguments
576   * @return
577   */
578  String formatMessage(String theMessage, Object... theMessageArguments);
579  String formatMessagePlural(Integer pluralNum, String theMessage, Object... theMessageArguments);
580
581  /**
582   * Validation of a code - consult the terminology infrstructure and/or service 
583   * to see whether it is known. If known, return a description of it
584   * 
585   * note: always return a result, with either an error or a code description
586   *  
587   * corresponds to 2 terminology service calls: $validate-code and $lookup
588   * 
589   * in this case, the system will be inferred from the value set. It's an error to call this one without the value set
590   * 
591   * @param options - validation options (required)
592   * @param code he code to validate (required)
593   * @param vs the applicable valueset (required)
594   * @return
595   */
596  public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
597
598  /**
599   * Validation of a code - consult the terminology infrstructure and/or service 
600   * to see whether it is known. If known, return a description of it
601   * 
602   * note: always return a result, with either an error or a code description
603   *  
604   * corresponds to 2 terminology service calls: $validate-code and $lookup
605   * 
606   * @param options - validation options (required)
607   * @param system - equals Coding.system (required)
608   * @param code - equals Coding.code (required)
609   * @param display - equals Coding.display (optional)
610   * @return
611   */
612  public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display);
613
614  /**
615   * Validation of a code - consult the terminology infrstructure and/or service 
616   * to see whether it is known. If known, return a description of it
617   * 
618   * note: always return a result, with either an error or a code description
619   *  
620   * corresponds to 2 terminology service calls: $validate-code and $lookup
621   * 
622   * @param options - validation options (required)
623   * @param system - equals Coding.system (required)
624   * @param code - equals Coding.code (required)
625   * @param display - equals Coding.display (optional)
626   * @param vs the applicable valueset (optional)
627   * @return
628   */
629  public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display, ValueSet vs);
630
631  /**
632   * Validation of a code - consult the terminology infrstructure and/or service 
633   * to see whether it is known. If known, return a description of it
634   * 
635   * note: always return a result, with either an error or a code description
636   *  
637   * corresponds to 2 terminology service calls: $validate-code and $lookup
638   * 
639   * Note that this doesn't validate binding strength (e.g. is just text allowed?)
640   * 
641   * @param options - validation options (required)
642   * @param code - CodeableConcept to validate
643   * @param vs the applicable valueset (optional)
644   * @return
645   */
646  public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs);
647
648  /**
649   * Validation of a code - consult the terminology infrstructure and/or service 
650   * to see whether it is known. If known, return a description of it
651   * 
652   * note: always return a result, with either an error or a code description
653   *  
654   * corresponds to 2 terminology service calls: $validate-code and $lookup
655   * 
656   * in this case, the system will be inferred from the value set. It's an error to call this one without the value set
657   * 
658   * @param options - validation options (required)
659   * @param code - Coding to validate
660   * @param vs the applicable valueset (optional)
661   * @return
662   */
663  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
664
665  /** 
666   * See comments in ValidationContextCarrier. This is called when there might be additional value sets etc 
667   * available in the context, but we don't want to pre-process them. 
668   * 
669   * @param options
670   * @param code
671   * @param vs
672   * @param ctxt
673   * @return
674   */
675  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt);
676
677  /**
678   * Batch validate code - reduce latency and do a bunch of codes in a single server call. 
679   * Each is the same as a validateCode
680   * 
681   * @param options
682   * @param codes
683   * @param vs
684   */
685  public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs, boolean passVS);
686  public OperationOutcome validateTxResource(ValidationOptions options, Resource resource);
687
688  // todo: figure these out
689  public Map<String, NamingSystem> getNSUrlMap();
690
691  public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger);
692  public org.hl7.fhir.r5.context.ILoggingService getLogger();
693
694  public boolean isNoTerminologyServer();
695  public Set<String> getCodeSystemsUsed();
696  public int getClientRetryCount();
697  public IWorkerContext setClientRetryCount(int value);
698
699  public TimeTracker clock();
700
701  /**
702   * This is a short cut for fetchResource(StructureDefinition.class, ...)
703   * but it accepts a typename - that is, it resolves based on StructureDefinition.type 
704   * or StructureDefinition.url. This only resolves to http://hl7.org/fhir/StructureDefinition/{typename}
705   * 
706   * @param typeName
707   * @return
708   */
709  public StructureDefinition fetchTypeDefinition(String typeName);
710  public StructureDefinition fetchTypeDefinition(String typeName, FhirPublication fhirVersion);
711
712  /**
713   * This finds all the structure definitions that have the given typeName
714   * 
715   * @param typeName
716   * @return
717   */
718  public List<StructureDefinition> fetchTypeDefinitions(String n);
719  public List<StructureDefinition> fetchTypeDefinitions(String n, FhirPublication fhirVersion);
720
721  /**
722   * return whether type is primitive type. This is called a lot, and needs a high performance implementation 
723   * @param type
724   * @return
725   */
726  public boolean isPrimitiveType(String type);
727
728  /**
729   * return whether type is data type. This is called a lot, and needs a high performance implementation 
730   * @param type
731   * @return
732   */
733  public boolean isDataType(String type);
734  
735  /**
736   * Returns a set of keys that can be used to get binaries from this context.
737   * The binaries come from the loaded packages (mostly the pubpack)
738   *
739   * @return a set of binaries or null
740   */
741  public Set<String> getBinaryKeysAsSet();
742
743  /**
744   * Returns true if this worker context contains a binary for this key.
745   *
746   * @param binaryKey
747   * @return true if binary is available for this key
748   */
749  public boolean hasBinaryKey(String binaryKey);
750
751  /**
752   * Returns the binary for the key
753   * @param binaryKey
754   * @return
755   */
756  public byte[] getBinaryForKey(String binaryKey);
757
758  /*
759   * Todo: move these loaders out to IWorkerContextManager
760   * 
761   */
762  /**
763   * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package
764   * 
765   * 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
766   * 
767   * @param pi - the package to load
768   * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version).
769   * @return the number of resources loaded
770   */
771  int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException;
772
773  /**
774   * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package
775   * 
776   * 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
777   *
778   * This method also loads all the packages that the package depends on (recursively)
779   * 
780   * @param pi - the package to load
781   * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version).
782   * @param pcm - used to find and load additional dependencies
783   * @return the number of resources loaded
784   */
785  int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException;
786
787  public boolean hasPackage(String id, String ver);
788  public boolean hasPackage(PackageInformation pack);
789  public PackageInformation getPackage(String id, String ver);
790  public PackageInformation getPackageForUrl(String url);
791
792  public IWorkerContextManager.IPackageLoadingTracker getPackageTracker();
793  public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker);
794
795  public String getSpecUrl();
796
797  public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps, boolean fixedProps);
798  
799  public boolean isForPublication();
800  public void setForPublication(boolean value);
801
802  /**
803   * 
804   * @param oid
805   * @param resourceType - null to search on all resource types
806   * @return
807   */
808  public OIDSummary urlsForOid(String oid, String resourceType);
809
810  /**
811   * this first does a fetch resource, and if nothing is found, looks in the 
812   * terminology eco-system for a matching definition for the resource 
813   * 
814   * usually used (and so far only tested with) ValueSet.class
815   * 
816   * @param value
817   * @return
818   */
819  public <T extends Resource> T findTxResource(Class<T> class_, String canonical, Resource sourceOfReference);
820  public <T extends Resource> T findTxResource(Class<T> class_, String canonical);
821  public <T extends Resource> T findTxResource(Class<T> class_, String canonical, String version);
822
823  /**
824   * ask the terminology system whether parent subsumes child. 
825   * 
826   * @return true if it does, false if it doesn't, and null if it's not know whether it does
827   */
828  public Boolean subsumes(ValidationOptions options, Coding parent, Coding child);
829
830  public boolean isServerSideSystem(String url);
831
832  class SystemSupportInformation {
833    // whether the ssytem(/version) is supported
834    @Getter
835    private boolean supported;
836
837    // the server that supports the system(/version)
838    // maybe null for some systems where we never consult any server
839    @Getter
840    private String server;
841
842    // if the server supports it, the set of test cases the server claims to pass (or null)
843    @Getter
844    private String testVersion;
845
846    public SystemSupportInformation(boolean supported, String server, String testVersion) {
847      this.supported = supported;
848      this.server = server;
849      this.testVersion = testVersion;
850    }
851
852    public SystemSupportInformation(boolean supported) {
853      this.supported = supported;
854    }
855  }
856}