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, FhirPublication 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  void setLocale(Locale locale);
556
557  @Deprecated
558  void setValidationMessageLanguage(Locale locale);
559
560  /**
561   * Access to the contexts internationalised error messages
562   * 
563   * For rendering internationalization, see RenderingContext
564   *  
565   * @param theMessage
566   * @param theMessageArguments
567   * @return
568   */
569  String formatMessage(String theMessage, Object... theMessageArguments);
570  String formatMessagePlural(Integer pluralNum, String theMessage, Object... theMessageArguments);
571
572  /**
573   * Validation of a code - consult the terminology infrstructure and/or service 
574   * to see whether it is known. If known, return a description of it
575   * 
576   * note: always return a result, with either an error or a code description
577   *  
578   * corresponds to 2 terminology service calls: $validate-code and $lookup
579   * 
580   * in this case, the system will be inferred from the value set. It's an error to call this one without the value set
581   * 
582   * @param options - validation options (required)
583   * @param code he code to validate (required)
584   * @param vs the applicable valueset (required)
585   * @return
586   */
587  public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
588
589  /**
590   * Validation of a code - consult the terminology infrstructure and/or service 
591   * to see whether it is known. If known, return a description of it
592   * 
593   * note: always return a result, with either an error or a code description
594   *  
595   * corresponds to 2 terminology service calls: $validate-code and $lookup
596   * 
597   * @param options - validation options (required)
598   * @param system - equals Coding.system (required)
599   * @param code - equals Coding.code (required)
600   * @param display - equals Coding.display (optional)
601   * @return
602   */
603  public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display);
604
605  /**
606   * Validation of a code - consult the terminology infrstructure and/or service 
607   * to see whether it is known. If known, return a description of it
608   * 
609   * note: always return a result, with either an error or a code description
610   *  
611   * corresponds to 2 terminology service calls: $validate-code and $lookup
612   * 
613   * @param options - validation options (required)
614   * @param system - equals Coding.system (required)
615   * @param code - equals Coding.code (required)
616   * @param display - equals Coding.display (optional)
617   * @param vs the applicable valueset (optional)
618   * @return
619   */
620  public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display, ValueSet vs);
621
622  /**
623   * Validation of a code - consult the terminology infrstructure and/or service 
624   * to see whether it is known. If known, return a description of it
625   * 
626   * note: always return a result, with either an error or a code description
627   *  
628   * corresponds to 2 terminology service calls: $validate-code and $lookup
629   * 
630   * Note that this doesn't validate binding strength (e.g. is just text allowed?)
631   * 
632   * @param options - validation options (required)
633   * @param code - CodeableConcept to validate
634   * @param vs the applicable valueset (optional)
635   * @return
636   */
637  public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs);
638
639  /**
640   * Validation of a code - consult the terminology infrstructure and/or service 
641   * to see whether it is known. If known, return a description of it
642   * 
643   * note: always return a result, with either an error or a code description
644   *  
645   * corresponds to 2 terminology service calls: $validate-code and $lookup
646   * 
647   * in this case, the system will be inferred from the value set. It's an error to call this one without the value set
648   * 
649   * @param options - validation options (required)
650   * @param code - Coding to validate
651   * @param vs the applicable valueset (optional)
652   * @return
653   */
654  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
655
656  /** 
657   * See comments in ValidationContextCarrier. This is called when there might be additional value sets etc 
658   * available in the context, but we don't want to pre-process them. 
659   * 
660   * @param options
661   * @param code
662   * @param vs
663   * @param ctxt
664   * @return
665   */
666  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs, ValidationContextCarrier ctxt);
667
668  /**
669   * Batch validate code - reduce latency and do a bunch of codes in a single server call. 
670   * Each is the same as a validateCode
671   * 
672   * @param options
673   * @param codes
674   * @param vs
675   */
676  public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs, boolean passVS);
677  public OperationOutcome validateTxResource(ValidationOptions options, Resource resource);
678
679  // todo: figure these out
680  public Map<String, NamingSystem> getNSUrlMap();
681
682  public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger);
683  public org.hl7.fhir.r5.context.ILoggingService getLogger();
684
685  public boolean isNoTerminologyServer();
686  public Set<String> getCodeSystemsUsed();
687  public int getClientRetryCount();
688  public IWorkerContext setClientRetryCount(int value);
689
690  public TimeTracker clock();
691
692  /**
693   * This is a short cut for fetchResource(StructureDefinition.class, ...)
694   * but it accepts a typename - that is, it resolves based on StructureDefinition.type 
695   * or StructureDefinition.url. This only resolves to http://hl7.org/fhir/StructureDefinition/{typename}
696   * 
697   * @param typeName
698   * @return
699   */
700  public StructureDefinition fetchTypeDefinition(String typeName);
701  public StructureDefinition fetchTypeDefinition(String typeName, FhirPublication fhirVersion);
702
703  /**
704   * This finds all the structure definitions that have the given typeName
705   * 
706   * @param typeName
707   * @return
708   */
709  public List<StructureDefinition> fetchTypeDefinitions(String n);
710  public List<StructureDefinition> fetchTypeDefinitions(String n, FhirPublication fhirVersion);
711
712  /**
713   * return whether type is primitive type. This is called a lot, and needs a high performance implementation 
714   * @param type
715   * @return
716   */
717  public boolean isPrimitiveType(String type);
718
719  /**
720   * return whether type is data type. This is called a lot, and needs a high performance implementation 
721   * @param type
722   * @return
723   */
724  public boolean isDataType(String type);
725  
726  /**
727   * Returns a set of keys that can be used to get binaries from this context.
728   * The binaries come from the loaded packages (mostly the pubpack)
729   *
730   * @return a set of binaries or null
731   */
732  public Set<String> getBinaryKeysAsSet();
733
734  /**
735   * Returns true if this worker context contains a binary for this key.
736   *
737   * @param binaryKey
738   * @return true if binary is available for this key
739   */
740  public boolean hasBinaryKey(String binaryKey);
741
742  /**
743   * Returns the binary for the key
744   * @param binaryKey
745   * @return
746   */
747  public byte[] getBinaryForKey(String binaryKey);
748
749  /*
750   * Todo: move these loaders out to IWorkerContextManager
751   * 
752   */
753  /**
754   * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package
755   * 
756   * 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
757   * 
758   * @param pi - the package to load
759   * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version).
760   * @return the number of resources loaded
761   */
762  int loadFromPackage(NpmPackage pi, IContextResourceLoader loader) throws FileNotFoundException, IOException, FHIRException;
763
764  /**
765   * Load relevant resources of the appropriate types (as specified by the loader) from the nominated package
766   * 
767   * 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
768   *
769   * This method also loads all the packages that the package depends on (recursively)
770   * 
771   * @param pi - the package to load
772   * @param loader - an implemenation of IContextResourceLoader that knows how to read the resources in the package (e.g. for the appropriate version).
773   * @param pcm - used to find and load additional dependencies
774   * @return the number of resources loaded
775   */
776  int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException;
777
778  public boolean hasPackage(String id, String ver);
779  public boolean hasPackage(PackageInformation pack);
780  public PackageInformation getPackage(String id, String ver);
781  public PackageInformation getPackageForUrl(String url);
782
783  public IWorkerContextManager.IPackageLoadingTracker getPackageTracker();
784  public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker);
785
786  public String getSpecUrl();
787
788  public PEBuilder getProfiledElementBuilder(PEElementPropertiesPolicy elementProps, boolean fixedProps);
789  
790  public boolean isForPublication();
791  public void setForPublication(boolean value);
792
793  /**
794   * 
795   * @param oid
796   * @param resourceType - null to search on all resource types
797   * @return
798   */
799  public OIDSummary urlsForOid(String oid, String resourceType);
800
801  /**
802   * this first does a fetch resource, and if nothing is found, looks in the 
803   * terminology eco-system for a matching definition for the resource 
804   * 
805   * usually used (and so far only tested with) ValueSet.class
806   * 
807   * @param value
808   * @return
809   */
810  public <T extends Resource> T findTxResource(Class<T> class_, String canonical, Resource sourceOfReference);
811  public <T extends Resource> T findTxResource(Class<T> class_, String canonical);
812  public <T extends Resource> T findTxResource(Class<T> class_, String canonical, String version);
813
814  /**
815   * ask the terminology system whether parent subsumes child. 
816   * 
817   * @return true if it does, false if it doesn't, and null if it's not know whether it does
818   */
819  public Boolean subsumes(ValidationOptions options, Coding parent, Coding child);
820
821  public boolean isServerSideSystem(String url);
822
823  class SystemSupportInformation {
824    // whether the ssytem(/version) is supported
825    @Getter
826    private boolean supported;
827
828    // the server that supports the system(/version)
829    // maybe null for some systems where we never consult any server
830    @Getter
831    private String server;
832
833    // if the server supports it, the set of test cases the server claims to pass (or null)
834    @Getter
835    private String testVersion;
836
837    public SystemSupportInformation(boolean supported, String server, String testVersion) {
838      this.supported = supported;
839      this.server = server;
840      this.testVersion = testVersion;
841    }
842
843    public SystemSupportInformation(boolean supported) {
844      this.supported = supported;
845    }
846  }
847}