001package org.hl7.fhir.r4.context;
002
003/*
004  Copyright (c) 2011+, HL7, Inc.
005  All rights reserved.
006  
007  Redistribution and use in source and binary forms, with or without modification, 
008  are permitted provided that the following conditions are met:
009    
010   * Redistributions of source code must retain the above copyright notice, this 
011     list of conditions and the following disclaimer.
012   * Redistributions in binary form must reproduce the above copyright notice, 
013     this list of conditions and the following disclaimer in the documentation 
014     and/or other materials provided with the distribution.
015   * Neither the name of HL7 nor the names of its contributors may be used to 
016     endorse or promote products derived from this software without specific 
017     prior written permission.
018  
019  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
020  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
021  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
022  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
023  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
024  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
025  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
026  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
027  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
028  POSSIBILITY OF SUCH DAMAGE.
029  
030 */
031
032import java.util.List;
033import java.util.Locale;
034import java.util.Set;
035
036import org.fhir.ucum.UcumService;
037import org.hl7.fhir.exceptions.DefinitionException;
038import org.hl7.fhir.exceptions.FHIRException;
039import org.hl7.fhir.exceptions.TerminologyServiceException;
040import org.hl7.fhir.r4.formats.IParser;
041import org.hl7.fhir.r4.formats.ParserType;
042import org.hl7.fhir.r4.model.CodeSystem;
043import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
044import org.hl7.fhir.r4.model.CodeableConcept;
045import org.hl7.fhir.r4.model.Coding;
046import org.hl7.fhir.r4.model.ConceptMap;
047import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent;
048import org.hl7.fhir.r4.model.MetadataResource;
049import org.hl7.fhir.r4.model.Parameters;
050import org.hl7.fhir.r4.model.Resource;
051import org.hl7.fhir.r4.model.StructureDefinition;
052import org.hl7.fhir.r4.model.StructureMap;
053import org.hl7.fhir.r4.model.ValueSet;
054import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
055import org.hl7.fhir.r4.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
056import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
057import org.hl7.fhir.r4.utils.INarrativeGenerator;
058import org.hl7.fhir.r4.utils.validation.IResourceValidator;
059import org.hl7.fhir.utilities.TranslationServices;
060import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
061import org.hl7.fhir.utilities.validation.ValidationOptions;
062
063/**
064 * This is the standard interface used for access to underlying FHIR services
065 * through the tools and utilities provided by the reference implementation.
066 * 
067 * The functionality it provides is - get access to parsers, validators,
068 * narrative builders etc (you can't create these directly because they need
069 * access to the right context for their information)
070 * 
071 * - find resources that the tools need to carry out their tasks
072 * 
073 * - provide access to terminology services they need. (typically, these
074 * terminology service requests are just passed through to the local
075 * implementation's terminology service)
076 * 
077 * @author Grahame
078 */
079public interface IWorkerContext {
080
081  /**
082   * Get the versions of the definitions loaded in context
083   * 
084   * @return
085   */
086  public String getVersion();
087
088  // get the UCUM service (might not be available)
089  public UcumService getUcumService();
090
091  // -- Parsers (read and write instances)
092  // ----------------------------------------
093
094  /**
095   * Get a parser to read/write instances. Use the defined type (will be extended
096   * as further types are added, though the only currently anticipate type is RDF)
097   * 
098   * XML/JSON - the standard renderers XHTML - render the narrative only (generate
099   * it if necessary)
100   * 
101   * @param type
102   * @return
103   */
104  public IParser getParser(ParserType type);
105
106  /**
107   * Get a parser to read/write instances. Determine the type from the stated
108   * type. Supported value for type: - the recommended MIME types - variants of
109   * application/xml and application/json - _format values xml, json
110   * 
111   * @param type
112   * @return
113   */
114  public IParser getParser(String type);
115
116  /**
117   * Get a JSON parser
118   * 
119   * @return
120   */
121  public IParser newJsonParser();
122
123  /**
124   * Get an XML parser
125   * 
126   * @return
127   */
128  public IParser newXmlParser();
129
130  /**
131   * Get a generator that can generate narrative for the instance
132   * 
133   * @return a prepared generator
134   */
135  public INarrativeGenerator getNarrativeGenerator(String prefix, String basePath);
136
137  /**
138   * Get a validator that can check whether a resource is valid
139   * 
140   * @return a prepared generator
141   * @throws FHIRException @
142   */
143  public IResourceValidator newValidator() throws FHIRException;
144
145  // -- resource fetchers ---------------------------------------------------
146
147  /**
148   * Find an identified resource. The most common use of this is to access the the
149   * standard conformance resources that are part of the standard - structure
150   * definitions, value sets, concept maps, etc.
151   * 
152   * Also, the narrative generator uses this, and may access any kind of resource
153   * 
154   * The URI is called speculatively for things that might exist, so not finding a
155   * matching resouce, return null, not an error
156   * 
157   * The URI can have one of 3 formats: - a full URL e.g.
158   * http://acme.org/fhir/ValueSet/[id] - a relative URL e.g. ValueSet/[id] - a
159   * logical id e.g. [id]
160   * 
161   * It's an error if the second form doesn't agree with class_. It's an error if
162   * class_ is null for the last form
163   * 
164   * @param resource
165   * @param Reference
166   * @return
167   * @throws FHIRException
168   * @throws Exception
169   */
170  public <T extends Resource> T fetchResource(Class<T> class_, String uri);
171
172  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
173
174  /**
175   * Variation of fetchResource when you have a string type, and don't need the
176   * right class
177   * 
178   * The URI can have one of 3 formats: - a full URL e.g.
179   * http://acme.org/fhir/ValueSet/[id] - a relative URL e.g. ValueSet/[id] - a
180   * logical id e.g. [id]
181   * 
182   * if type == null, the URI can't be a simple logical id
183   * 
184   * @param type
185   * @param uri
186   * @return
187   */
188  public Resource fetchResourceById(String type, String uri);
189
190  /**
191   * find whether a resource is available.
192   * 
193   * Implementations of the interface can assume that if hasResource ruturns true,
194   * the resource will usually be fetched subsequently
195   * 
196   * @param class_
197   * @param uri
198   * @return
199   */
200  public <T extends Resource> boolean hasResource(Class<T> class_, String uri);
201
202  /**
203   * cache a resource for later retrieval using fetchResource.
204   * 
205   * Note that various context implementations will have their own ways of loading
206   * rseources, and not all need implement cacheResource
207   * 
208   * @param res
209   * @throws FHIRException
210   */
211  public void cacheResource(Resource res) throws FHIRException;
212
213  // -- profile services ---------------------------------------------------------
214
215  public List<String> getResourceNames();
216
217  public Set<String> getResourceNamesAsSet();
218
219  public List<String> getTypeNames();
220
221  public List<StructureDefinition> allStructures(); // ensure snapshot exists...
222
223  public List<StructureDefinition> getStructures();
224
225  public List<MetadataResource> allConformanceResources();
226
227  public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException;
228
229  // -- Terminology services
230  // ------------------------------------------------------
231
232  public Parameters getExpansionParameters();
233
234  public void setExpansionProfile(Parameters expParameters);
235
236  // these are the terminology services used internally by the tools
237  /**
238   * Find the code system definition for the nominated system uri. return null if
239   * there isn't one (then the tool might try supportsSystem)
240   * 
241   * @param system
242   * @return
243   */
244  public CodeSystem fetchCodeSystem(String system);
245
246  /**
247   * True if the underlying terminology service provider will do expansion and
248   * code validation for the terminology. Corresponds to the extension
249   * 
250   * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system
251   * 
252   * in the Conformance resource
253   * 
254   * @param system
255   * @return
256   * @throws Exception
257   */
258  public boolean supportsSystem(String system) throws TerminologyServiceException;
259
260  /**
261   * find concept maps for a source
262   * 
263   * @param url
264   * @return
265   * @throws FHIRException
266   */
267  public List<ConceptMap> findMapsForSource(String url) throws FHIRException;
268
269  /**
270   * ValueSet Expansion - see $expand
271   * 
272   * @param source
273   * @return
274   */
275  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
276
277  /**
278   * ValueSet Expansion - see $expand, but resolves the binding first
279   * 
280   * @param source
281   * @return
282   * @throws FHIRException
283   */
284  public ValueSetExpansionOutcome expandVS(ElementDefinitionBindingComponent binding, boolean cacheOk,
285      boolean heiarchical) throws FHIRException;
286
287  /**
288   * Value set expanion inside the internal expansion engine - used for references
289   * to supported system (see "supportsSystem") for which there is no value set.
290   * 
291   * @param inc
292   * @return
293   * @throws FHIRException
294   */
295  public ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean heirarchical)
296      throws TerminologyServiceException;
297
298  Locale getLocale();
299
300  void setLocale(Locale locale);
301
302  String formatMessage(String theMessage, Object... theMessageArguments);
303
304  String formatMessagePlural(Integer pl, String theMessage, Object... theMessageArguments);
305
306  void setValidationMessageLanguage(Locale locale);
307
308  public class ValidationResult {
309    private ConceptDefinitionComponent definition;
310    private IssueSeverity severity;
311    private String message;
312    private TerminologyServiceErrorClass errorClass;
313    private String txLink;
314
315    public ValidationResult(IssueSeverity severity, String message) {
316      this.severity = severity;
317      this.message = message;
318    }
319
320    public ValidationResult(ConceptDefinitionComponent definition) {
321      this.definition = definition;
322    }
323
324    public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
325      this.severity = severity;
326      this.message = message;
327      this.definition = definition;
328    }
329
330    public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
331      this.severity = severity;
332      this.message = message;
333      this.errorClass = errorClass;
334    }
335
336    public boolean isOk() {
337      return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING;
338    }
339
340    public String getDisplay() {
341// 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
342//      return definition == null ? "??" : definition.getDisplay();
343      return definition == null ? null : definition.getDisplay();
344    }
345
346    public ConceptDefinitionComponent asConceptDefinition() {
347      return definition;
348    }
349
350    public IssueSeverity getSeverity() {
351      return severity;
352    }
353
354    public String getMessage() {
355      return message;
356    }
357
358    public boolean IsNoService() {
359      return errorClass == TerminologyServiceErrorClass.NOSERVICE;
360    }
361
362    public TerminologyServiceErrorClass getErrorClass() {
363      return errorClass;
364    }
365
366    public ValidationResult setSeverity(IssueSeverity severity) {
367      this.severity = severity;
368      return this;
369    }
370
371    public ValidationResult setMessage(String message) {
372      this.message = message;
373      return this;
374    }
375
376    public String getTxLink() {
377      return txLink;
378    }
379
380    public ValidationResult setTxLink(String txLink) {
381      this.txLink = txLink;
382      return this;
383    }
384
385  }
386
387  /**
388   * Validation of a code - consult the terminology service to see whether it is
389   * known. If known, return a description of it
390   * 
391   * note: always return a result, with either an error or a code description
392   * 
393   * corresponds to 2 terminology service calls: $validate-code and $lookup
394   * 
395   * @param system
396   * @param code
397   * @param display
398   * @return
399   */
400  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display);
401
402  /**
403   * Validation of a code - consult the terminology service to see whether it is
404   * known. If known, return a description of it Also, check whether it's in the
405   * provided value set
406   * 
407   * note: always return a result, with either an error or a code description, or
408   * both (e.g. known code, but not in the value set)
409   * 
410   * corresponds to 2 terminology service calls: $validate-code and $lookup
411   * 
412   * @param system
413   * @param code
414   * @param display
415   * @return
416   */
417  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display,
418      ValueSet vs);
419
420  public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
421
422  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
423
424  public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs);
425
426  /**
427   * Validation of a code - consult the terminology service to see whether it is
428   * known. If known, return a description of it Also, check whether it's in the
429   * provided value set fragment (for supported systems with no value set
430   * definition)
431   * 
432   * note: always return a result, with either an error or a code description, or
433   * both (e.g. known code, but not in the value set)
434   * 
435   * corresponds to 2 terminology service calls: $validate-code and $lookup
436   * 
437   * @param system
438   * @param code
439   * @param display
440   * @return
441   */
442  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display,
443      ConceptSetComponent vsi);
444
445  /**
446   * returns the recommended tla for the type
447   * 
448   * @param name
449   * @return
450   */
451  public String getAbbreviation(String name);
452
453  // return a set of types that have tails
454  public Set<String> typeTails();
455
456  public String oid2Uri(String code);
457
458  public boolean hasCache();
459
460  public interface ILoggingService {
461    public enum LogCategory {
462      PROGRESS, TX, INIT, CONTEXT, HTML
463    }
464
465    public void logMessage(String message); // status messages, always display
466
467    public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging
468  }
469
470  public void setLogger(ILoggingService logger);
471
472  public ILoggingService getLogger();
473
474  public boolean isNoTerminologyServer();
475
476  public TranslationServices translator();
477
478  public List<StructureMap> listTransforms();
479
480  public StructureMap getTransform(String url);
481
482  public String getOverrideVersionNs();
483
484  public void setOverrideVersionNs(String value);
485
486  public StructureDefinition fetchTypeDefinition(String typeName);
487
488  public void setUcumService(UcumService ucumService);
489
490  public String getLinkForUrl(String corePath, String s);
491}