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  void setValidationMessageLanguage(Locale locale);
303
304  public class ValidationResult {
305    private ConceptDefinitionComponent definition;
306    private IssueSeverity severity;
307    private String message;
308    private TerminologyServiceErrorClass errorClass;
309    private String txLink;
310    
311    public ValidationResult(IssueSeverity severity, String message) {
312      this.severity = severity;
313      this.message = message;
314    }
315    
316    public ValidationResult(ConceptDefinitionComponent definition) {
317      this.definition = definition;
318    }
319
320    public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
321      this.severity = severity;
322      this.message = message;
323      this.definition = definition;
324    }
325    
326    public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
327      this.severity = severity;
328      this.message = message;
329      this.errorClass = errorClass;
330    }
331
332    public boolean isOk() {
333      return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING;
334    }
335
336    public String getDisplay() {
337// 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
338//      return definition == null ? "??" : definition.getDisplay();
339      return definition == null ? null : definition.getDisplay();
340    }
341
342    public ConceptDefinitionComponent asConceptDefinition() {
343      return definition;
344    }
345
346    public IssueSeverity getSeverity() {
347      return severity;
348    }
349
350    public String getMessage() {
351      return message;
352    }
353
354    public boolean IsNoService() {
355      return errorClass == TerminologyServiceErrorClass.NOSERVICE;
356    }
357
358    public TerminologyServiceErrorClass getErrorClass() {
359      return errorClass;
360    }
361
362    public ValidationResult setSeverity(IssueSeverity severity) {
363      this.severity = severity;
364      return this;
365    }
366
367    public ValidationResult setMessage(String message) {
368      this.message = message;
369      return this;
370    }
371
372    public String getTxLink() {
373      return txLink;
374    }
375
376    public ValidationResult setTxLink(String txLink) {
377      this.txLink = txLink;
378      return this;
379    }
380    
381    
382  }
383
384  /**
385   * Validation of a code - consult the terminology service 
386   * to see whether it is known. If known, return a description of it
387   * 
388   *  note: always return a result, with either an error or a code description
389   *  
390   * corresponds to 2 terminology service calls: $validate-code and $lookup
391   * 
392   * @param system
393   * @param code
394   * @param display
395   * @return
396   */
397  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display);
398
399  /**
400   * Validation of a code - consult the terminology service 
401   * to see whether it is known. If known, return a description of it
402   * Also, check whether it's in the provided value set
403   * 
404   * 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)
405   *  
406   * corresponds to 2 terminology service calls: $validate-code and $lookup
407   * 
408   * @param system
409   * @param code
410   * @param display
411   * @return
412   */
413  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, ValueSet vs);
414  public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
415  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
416  public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs);
417  
418  /**
419   * Validation of a code - consult the terminology service 
420   * to see whether it is known. If known, return a description of it
421   * Also, check whether it's in the provided value set fragment (for supported systems with no value set definition)
422   * 
423   * 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)
424   *  
425   * corresponds to 2 terminology service calls: $validate-code and $lookup
426   * 
427   * @param system
428   * @param code
429   * @param display
430   * @return
431   */
432  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, ConceptSetComponent vsi);
433
434  /**
435   * returns the recommended tla for the type 
436   * 
437   * @param name
438   * @return
439   */
440  public String getAbbreviation(String name);
441
442  // return a set of types that have tails
443  public Set<String> typeTails();
444
445        public String oid2Uri(String code);
446
447  public boolean hasCache();
448
449  public interface ILoggingService {
450    public enum LogCategory {
451      PROGRESS, TX, INIT, CONTEXT, HTML 
452    }
453    public void logMessage(String message); // status messages, always display
454    public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging 
455  }
456
457  public void setLogger(ILoggingService logger);
458  public ILoggingService getLogger();
459
460  public boolean isNoTerminologyServer();
461
462  public TranslationServices translator();
463  public List<StructureMap> listTransforms();
464  public StructureMap getTransform(String url);
465
466  public String getOverrideVersionNs();
467  public void setOverrideVersionNs(String value);
468
469  public StructureDefinition fetchTypeDefinition(String typeName);
470
471  public void setUcumService(UcumService ucumService);
472
473  public String getLinkForUrl(String corePath, String s);
474}