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