001package org.hl7.fhir.r4.context;
002
003import java.util.List;
004import java.util.Set;
005
006import org.hl7.fhir.r4.formats.IParser;
007import org.hl7.fhir.r4.formats.ParserType;
008import org.hl7.fhir.r4.model.CodeSystem;
009import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
010import org.hl7.fhir.r4.model.CodeableConcept;
011import org.hl7.fhir.r4.model.Coding;
012import org.hl7.fhir.r4.model.ConceptMap;
013import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent;
014import org.hl7.fhir.r4.model.ExpansionProfile;
015import org.hl7.fhir.r4.model.MetadataResource;
016import org.hl7.fhir.r4.model.Resource;
017import org.hl7.fhir.r4.model.StructureDefinition;
018import org.hl7.fhir.r4.model.StructureMap;
019import org.hl7.fhir.r4.model.ValueSet;
020import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
021import org.hl7.fhir.r4.model.ValueSet.ValueSetExpansionComponent;
022import org.hl7.fhir.r4.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
023import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
024import org.hl7.fhir.r4.utils.INarrativeGenerator;
025import org.hl7.fhir.r4.utils.IResourceValidator;
026import org.fhir.ucum.UcumService;
027import org.hl7.fhir.exceptions.FHIRException;
028import org.hl7.fhir.exceptions.TerminologyServiceException;
029import org.hl7.fhir.utilities.TranslationServices;
030import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
031
032
033/**
034 * This is the standard interface used for access to underlying FHIR
035 * services through the tools and utilities provided by the reference
036 * implementation. 
037 * 
038 * The functionality it provides is 
039 *  - get access to parsers, validators, narrative builders etc
040 *    (you can't create these directly because they need access 
041 *    to the right context for their information)
042 *    
043 *  - find resources that the tools need to carry out their tasks
044 *  
045 *  - provide access to terminology services they need. 
046 *    (typically, these terminology service requests are just
047 *    passed through to the local implementation's terminology
048 *    service)    
049 *  
050 * @author Grahame
051 */
052public interface IWorkerContext {
053
054  /**
055   * Get the versions of the definitions loaded in context
056   * @return
057   */
058  public String getVersion();
059  
060  // get the UCUM service (might not be available)
061  public UcumService getUcumService();
062  
063  // -- Parsers (read and write instances) ----------------------------------------
064
065
066  /**
067   * Get a parser to read/write instances. Use the defined type (will be extended 
068   * as further types are added, though the only currently anticipate type is RDF)
069   * 
070   * XML/JSON - the standard renderers
071   * XHTML - render the narrative only (generate it if necessary)
072   * 
073   * @param type
074   * @return
075   */
076  public IParser getParser(ParserType type);
077
078  /**
079   * Get a parser to read/write instances. Determine the type 
080   * from the stated type. Supported value for type:
081   * - the recommended MIME types
082   * - variants of application/xml and application/json
083   * - _format values xml, json
084   * 
085   * @param type
086   * @return
087   */   
088  public IParser getParser(String type);
089
090  /**
091   * Get a JSON parser
092   * 
093   * @return
094   */
095  public IParser newJsonParser();
096
097  /**
098   * Get an XML parser
099   * 
100   * @return
101   */
102  public IParser newXmlParser();
103
104  /**
105   * Get a generator that can generate narrative for the instance
106   * 
107   * @return a prepared generator
108   */
109  public INarrativeGenerator getNarrativeGenerator(String prefix, String basePath);
110
111  /**
112   * Get a validator that can check whether a resource is valid 
113   * 
114   * @return a prepared generator
115   * @throws FHIRException 
116   * @
117   */
118  public IResourceValidator newValidator() throws FHIRException;
119
120  // -- resource fetchers ---------------------------------------------------
121
122  /**
123   * Find an identified resource. The most common use of this is to access the the 
124   * standard conformance resources that are part of the standard - structure 
125   * definitions, value sets, concept maps, etc.
126   * 
127   * Also, the narrative generator uses this, and may access any kind of resource
128   * 
129   * The URI is called speculatively for things that might exist, so not finding 
130   * a matching resouce, return null, not an error
131   * 
132   * The URI can have one of 3 formats:
133   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
134   *  - a relative URL e.g. ValueSet/[id]
135   *  - a logical id e.g. [id]
136   *  
137   * It's an error if the second form doesn't agree with class_. It's an 
138   * error if class_ is null for the last form
139   * 
140   * @param resource
141   * @param Reference
142   * @return
143   * @throws FHIRException 
144   * @throws Exception
145   */
146  public <T extends Resource> T fetchResource(Class<T> class_, String uri);
147  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
148
149  /**
150   * Variation of fetchResource when you have a string type, and don't need the right class
151   * 
152   * The URI can have one of 3 formats:
153   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
154   *  - a relative URL e.g. ValueSet/[id]
155   *  - a logical id e.g. [id]
156   *  
157   * if type == null, the URI can't be a simple logical id
158   * 
159   * @param type
160   * @param uri
161   * @return
162   */
163  public Resource fetchResourceById(String type, String uri);
164  
165  /**
166   * find whether a resource is available. 
167   * 
168   * Implementations of the interface can assume that if hasResource ruturns 
169   * true, the resource will usually be fetched subsequently
170   * 
171   * @param class_
172   * @param uri
173   * @return
174   */
175  public <T extends Resource> boolean hasResource(Class<T> class_, String uri);
176
177  /**
178   * cache a resource for later retrieval using fetchResource.
179   * 
180   * Note that various context implementations will have their own ways of loading
181   * rseources, and not all need implement cacheResource 
182   * @param res
183   * @throws FHIRException 
184   */
185  public void cacheResource(Resource res) throws FHIRException;
186  
187  // -- profile services ---------------------------------------------------------
188  
189  public List<String> getResourceNames();
190  public Set<String> getResourceNamesAsSet();
191  public List<String> getTypeNames();
192  public List<StructureDefinition> allStructures();
193  public List<MetadataResource> allConformanceResources();
194  
195  // -- Terminology services ------------------------------------------------------
196
197  public ExpansionProfile getExpansionProfile();
198  public void setExpansionProfile(ExpansionProfile expProfile);
199
200  // these are the terminology services used internally by the tools
201  /**
202   * Find the code system definition for the nominated system uri. 
203   * return null if there isn't one (then the tool might try 
204   * supportsSystem)
205   * 
206   * @param system
207   * @return
208   */
209  public CodeSystem fetchCodeSystem(String system);
210
211  /**
212   * True if the underlying terminology service provider will do 
213   * expansion and code validation for the terminology. Corresponds
214   * to the extension 
215   * 
216   * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system
217   * 
218   * in the Conformance resource
219   * 
220   * @param system
221   * @return
222   * @throws Exception 
223   */
224  public boolean supportsSystem(String system) throws TerminologyServiceException;
225
226  /**
227   * find concept maps for a source
228   * @param url
229   * @return
230   * @throws FHIRException 
231   */
232  public List<ConceptMap> findMapsForSource(String url) throws FHIRException;  
233
234  /**
235   * ValueSet Expansion - see $expand
236   *  
237   * @param source
238   * @return
239   */
240  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
241  
242  /**
243   * ValueSet Expansion - see $expand, but resolves the binding first
244   *  
245   * @param source
246   * @return
247   * @throws FHIRException 
248   */
249  public ValueSetExpansionOutcome expandVS(ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) throws FHIRException;
250  /**
251   * Value set expanion inside the internal expansion engine - used 
252   * for references to supported system (see "supportsSystem") for
253   * which there is no value set. 
254   * 
255   * @param inc
256   * @return
257   * @throws FHIRException 
258   */
259  public ValueSetExpansionComponent expandVS(ConceptSetComponent inc, boolean heirarchical) throws TerminologyServiceException;
260  
261  public class ValidationResult {
262    private ConceptDefinitionComponent definition;
263    private IssueSeverity severity;
264    private String message;
265    private TerminologyServiceErrorClass errorClass;
266    
267    public ValidationResult(IssueSeverity severity, String message) {
268      this.severity = severity;
269      this.message = message;
270    }
271    
272    public ValidationResult(ConceptDefinitionComponent definition) {
273      this.definition = definition;
274    }
275
276    public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
277      this.severity = severity;
278      this.message = message;
279      this.definition = definition;
280    }
281    
282    public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
283      this.severity = severity;
284      this.message = message;
285      this.errorClass = errorClass;
286    }
287
288    public boolean isOk() {
289      return definition != null;
290    }
291
292    public String getDisplay() {
293// We don't want to return question-marks because that prevents something more useful from being displayed (e.g. the code) if there's no display value
294//      return definition == null ? "??" : definition.getDisplay();
295      return definition == null ? null : definition.getDisplay();
296    }
297
298    public ConceptDefinitionComponent asConceptDefinition() {
299      return definition;
300    }
301
302    public IssueSeverity getSeverity() {
303      return severity;
304    }
305
306    public String getMessage() {
307      return message;
308    }
309
310    public boolean IsNoService() {
311      return errorClass == TerminologyServiceErrorClass.NOSERVICE;
312    }
313
314    public TerminologyServiceErrorClass getErrorClass() {
315      return errorClass;
316    }
317    
318    
319  }
320
321  /**
322   * Validation of a code - consult the terminology service 
323   * to see whether it is known. If known, return a description of it
324   * 
325   *  note: always return a result, with either an error or a code description
326   *  
327   * corresponds to 2 terminology service calls: $validate-code and $lookup
328   * 
329   * @param system
330   * @param code
331   * @param display
332   * @return
333   */
334  public ValidationResult validateCode(String system, String code, String display);
335
336  /**
337   * Validation of a code - consult the terminology service 
338   * to see whether it is known. If known, return a description of it
339   * Also, check whether it's in the provided value set
340   * 
341   * note: always return a result, with either an error or a code description, or both (e.g. known code, but not in the value set)
342   *  
343   * corresponds to 2 terminology service calls: $validate-code and $lookup
344   * 
345   * @param system
346   * @param code
347   * @param display
348   * @return
349   */
350  public ValidationResult validateCode(String system, String code, String display, ValueSet vs);
351  public ValidationResult validateCode(Coding code, ValueSet vs);
352  public ValidationResult validateCode(CodeableConcept code, ValueSet vs);
353  
354  /**
355   * Validation of a code - consult the terminology service 
356   * to see whether it is known. If known, return a description of it
357   * Also, check whether it's in the provided value set fragment (for supported systems with no value set definition)
358   * 
359   * note: always return a result, with either an error or a code description, or both (e.g. known code, but not in the value set)
360   *  
361   * corresponds to 2 terminology service calls: $validate-code and $lookup
362   * 
363   * @param system
364   * @param code
365   * @param display
366   * @return
367   */
368  public ValidationResult validateCode(String system, String code, String display, ConceptSetComponent vsi);
369
370  /**
371   * returns the recommended tla for the type 
372   * 
373   * @param name
374   * @return
375   */
376  public String getAbbreviation(String name);
377
378  // return a set of types that have tails
379  public Set<String> typeTails();
380
381        public String oid2Uri(String code);
382
383  public boolean hasCache();
384
385  public interface ILoggingService {
386    public enum LogCategory {
387      PROGRESS, TX, INIT, CONTEXT, HTML 
388    }
389    public void logMessage(String message); // status messages, always display
390    public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging 
391  }
392
393  public void setLogger(ILoggingService logger);
394
395  public boolean isNoTerminologyServer();
396
397  public TranslationServices translator();
398  public List<StructureMap> listTransforms();
399  public StructureMap getTransform(String url);
400}