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