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.Set;
037
038import org.fhir.ucum.UcumService;
039import org.hl7.fhir.exceptions.DefinitionException;
040import org.hl7.fhir.exceptions.FHIRException;
041import org.hl7.fhir.exceptions.TerminologyServiceException;
042import org.hl7.fhir.r4.formats.IParser;
043import org.hl7.fhir.r4.formats.ParserType;
044import org.hl7.fhir.r4.model.CodeSystem;
045import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent;
046import org.hl7.fhir.r4.model.CodeableConcept;
047import org.hl7.fhir.r4.model.Coding;
048import org.hl7.fhir.r4.model.ConceptMap;
049import org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent;
050import org.hl7.fhir.r4.model.MetadataResource;
051import org.hl7.fhir.r4.model.Parameters;
052import org.hl7.fhir.r4.model.Resource;
053import org.hl7.fhir.r4.model.StructureDefinition;
054import org.hl7.fhir.r4.model.StructureMap;
055import org.hl7.fhir.r4.model.ValueSet;
056import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
057import org.hl7.fhir.r4.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
058import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
059import org.hl7.fhir.r4.utils.INarrativeGenerator;
060import org.hl7.fhir.r4.utils.validation.IResourceValidator;
061import org.hl7.fhir.utilities.TranslationServices;
062import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
063import org.hl7.fhir.utilities.validation.ValidationOptions;
064
065
066/**
067 * This is the standard interface used for access to underlying FHIR
068 * services through the tools and utilities provided by the reference
069 * implementation. 
070 * 
071 * The functionality it provides is 
072 *  - get access to parsers, validators, narrative builders etc
073 *    (you can't create these directly because they need access 
074 *    to the right context for their information)
075 *    
076 *  - find resources that the tools need to carry out their tasks
077 *  
078 *  - provide access to terminology services they need. 
079 *    (typically, these terminology service requests are just
080 *    passed through to the local implementation's terminology
081 *    service)    
082 *  
083 * @author Grahame
084 */
085public interface IWorkerContext {
086
087  /**
088   * Get the versions of the definitions loaded in context
089   * @return
090   */
091  public String getVersion();
092  
093  // get the UCUM service (might not be available)
094  public UcumService getUcumService();
095  
096  // -- Parsers (read and write instances) ----------------------------------------
097
098
099  /**
100   * Get a parser to read/write instances. Use the defined type (will be extended 
101   * as further types are added, though the only currently anticipate type is RDF)
102   * 
103   * XML/JSON - the standard renderers
104   * XHTML - render the narrative only (generate it if necessary)
105   * 
106   * @param type
107   * @return
108   */
109  public IParser getParser(ParserType type);
110
111  /**
112   * Get a parser to read/write instances. Determine the type 
113   * from the stated type. Supported value for type:
114   * - the recommended MIME types
115   * - variants of application/xml and application/json
116   * - _format values xml, json
117   * 
118   * @param type
119   * @return
120   */   
121  public IParser getParser(String type);
122
123  /**
124   * Get a JSON parser
125   * 
126   * @return
127   */
128  public IParser newJsonParser();
129
130  /**
131   * Get an XML parser
132   * 
133   * @return
134   */
135  public IParser newXmlParser();
136
137  /**
138   * Get a generator that can generate narrative for the instance
139   * 
140   * @return a prepared generator
141   */
142  public INarrativeGenerator getNarrativeGenerator(String prefix, String basePath);
143
144  /**
145   * Get a validator that can check whether a resource is valid 
146   * 
147   * @return a prepared generator
148   * @throws FHIRException 
149   * @
150   */
151  public IResourceValidator newValidator() throws FHIRException;
152
153  // -- resource fetchers ---------------------------------------------------
154
155  /**
156   * Find an identified resource. The most common use of this is to access the the 
157   * standard conformance resources that are part of the standard - structure 
158   * definitions, value sets, concept maps, etc.
159   * 
160   * Also, the narrative generator uses this, and may access any kind of resource
161   * 
162   * The URI is called speculatively for things that might exist, so not finding 
163   * a matching resouce, return null, not an error
164   * 
165   * The URI can have one of 3 formats:
166   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
167   *  - a relative URL e.g. ValueSet/[id]
168   *  - a logical id e.g. [id]
169   *  
170   * It's an error if the second form doesn't agree with class_. It's an 
171   * error if class_ is null for the last form
172   * 
173   * @param resource
174   * @param Reference
175   * @return
176   * @throws FHIRException 
177   * @throws Exception
178   */
179  public <T extends Resource> T fetchResource(Class<T> class_, String uri);
180  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
181
182  /**
183   * Variation of fetchResource when you have a string type, and don't need the right class
184   * 
185   * The URI can have one of 3 formats:
186   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
187   *  - a relative URL e.g. ValueSet/[id]
188   *  - a logical id e.g. [id]
189   *  
190   * if type == null, the URI can't be a simple logical id
191   * 
192   * @param type
193   * @param uri
194   * @return
195   */
196  public Resource fetchResourceById(String type, String uri);
197  
198  /**
199   * find whether a resource is available. 
200   * 
201   * Implementations of the interface can assume that if hasResource ruturns 
202   * true, the resource will usually be fetched subsequently
203   * 
204   * @param class_
205   * @param uri
206   * @return
207   */
208  public <T extends Resource> boolean hasResource(Class<T> class_, String uri);
209
210  /**
211   * cache a resource for later retrieval using fetchResource.
212   * 
213   * Note that various context implementations will have their own ways of loading
214   * rseources, and not all need implement cacheResource 
215   * @param res
216   * @throws FHIRException 
217   */
218  public void cacheResource(Resource res) throws FHIRException;
219  
220  // -- profile services ---------------------------------------------------------
221  
222  public List<String> getResourceNames();
223  public Set<String> getResourceNamesAsSet();
224  public List<String> getTypeNames();
225  public List<StructureDefinition> allStructures(); // ensure snapshot exists...
226  public List<StructureDefinition> getStructures();
227  public List<MetadataResource> allConformanceResources();
228  public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException;
229  
230  // -- Terminology services ------------------------------------------------------
231
232  public Parameters getExpansionParameters();
233  public void setExpansionProfile(Parameters expParameters);
234
235  // these are the terminology services used internally by the tools
236  /**
237   * Find the code system definition for the nominated system uri. 
238   * return null if there isn't one (then the tool might try 
239   * 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 
248   * expansion and code validation for the terminology. Corresponds
249   * to the extension 
250   * 
251   * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system
252   * 
253   * in the Conformance resource
254   * 
255   * @param system
256   * @return
257   * @throws Exception 
258   */
259  public boolean supportsSystem(String system) throws TerminologyServiceException;
260
261  /**
262   * find concept maps for a source
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, boolean heiarchical) throws FHIRException;
285  /**
286   * Value set expanion inside the internal expansion engine - used 
287   * for references to supported system (see "supportsSystem") for
288   * which there is no value set. 
289   * 
290   * @param inc
291   * @return
292   * @throws FHIRException 
293   */
294  public ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean heirarchical) throws TerminologyServiceException;
295
296  Locale getLocale();
297
298  void setLocale(Locale locale);
299
300  String formatMessage(String theMessage, Object... theMessageArguments);
301
302  String formatMessagePlural(Integer pl, 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}