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  public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version);
172
173  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
174
175  /**
176   * Variation of fetchResource when you have a string type, and don't need the
177   * right class
178   * 
179   * The URI can have one of 3 formats: - a full URL e.g.
180   * http://acme.org/fhir/ValueSet/[id] - a relative URL e.g. ValueSet/[id] - a
181   * logical id e.g. [id]
182   * 
183   * if type == null, the URI can't be a simple logical id
184   * 
185   * @param type
186   * @param uri
187   * @return
188   */
189  public Resource fetchResourceById(String type, String uri);
190
191  /**
192   * find whether a resource is available.
193   * 
194   * Implementations of the interface can assume that if hasResource ruturns true,
195   * the resource will usually be fetched subsequently
196   * 
197   * @param class_
198   * @param uri
199   * @return
200   */
201  public <T extends Resource> boolean hasResource(Class<T> class_, String uri);
202
203  /**
204   * cache a resource for later retrieval using fetchResource.
205   * 
206   * Note that various context implementations will have their own ways of loading
207   * rseources, and not all need implement cacheResource
208   * 
209   * @param res
210   * @throws FHIRException
211   */
212  public void cacheResource(Resource res) throws FHIRException;
213
214  // -- profile services ---------------------------------------------------------
215
216  public List<String> getResourceNames();
217
218  public Set<String> getResourceNamesAsSet();
219
220  public List<String> getTypeNames();
221
222  public List<StructureDefinition> allStructures(); // ensure snapshot exists...
223
224  public List<StructureDefinition> getStructures();
225
226  public List<MetadataResource> allConformanceResources();
227
228  public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException;
229
230  // -- Terminology services
231  // ------------------------------------------------------
232
233  public Parameters getExpansionParameters();
234
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. return null if
240   * there isn't one (then the tool might try supportsSystem)
241   * 
242   * @param system
243   * @return
244   */
245  public CodeSystem fetchCodeSystem(String system);
246
247  /**
248   * True if the underlying terminology service provider will do expansion and
249   * code validation for the terminology. Corresponds 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   * 
264   * @param url
265   * @return
266   * @throws FHIRException
267   */
268  public List<ConceptMap> findMapsForSource(String url) throws FHIRException;
269
270  /**
271   * ValueSet Expansion - see $expand
272   * 
273   * @param source
274   * @return
275   */
276  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
277
278  /**
279   * ValueSet Expansion - see $expand, but resolves the binding first
280   * 
281   * @param source
282   * @return
283   * @throws FHIRException
284   */
285  public ValueSetExpansionOutcome expandVS(ElementDefinitionBindingComponent binding, boolean cacheOk,
286      boolean heiarchical) throws FHIRException;
287
288  /**
289   * Value set expanion inside the internal expansion engine - used for references
290   * to supported system (see "supportsSystem") for which there is no value set.
291   * 
292   * @param inc
293   * @return
294   * @throws FHIRException
295   */
296  public ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean heirarchical)
297      throws TerminologyServiceException;
298
299  Locale getLocale();
300
301  void setLocale(Locale locale);
302
303  String formatMessage(String theMessage, Object... theMessageArguments);
304
305  String formatMessagePlural(Integer pl, String theMessage, Object... theMessageArguments);
306
307  void setValidationMessageLanguage(Locale locale);
308
309  public class ValidationResult {
310    private ConceptDefinitionComponent definition;
311    private IssueSeverity severity;
312    private String message;
313    private TerminologyServiceErrorClass errorClass;
314    private String txLink;
315
316    public ValidationResult(IssueSeverity severity, String message) {
317      this.severity = severity;
318      this.message = message;
319    }
320
321    public ValidationResult(ConceptDefinitionComponent definition) {
322      this.definition = definition;
323    }
324
325    public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
326      this.severity = severity;
327      this.message = message;
328      this.definition = definition;
329    }
330
331    public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
332      this.severity = severity;
333      this.message = message;
334      this.errorClass = errorClass;
335    }
336
337    public boolean isOk() {
338      return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING;
339    }
340
341    public String getDisplay() {
342// 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
343//      return definition == null ? "??" : definition.getDisplay();
344      return definition == null ? null : definition.getDisplay();
345    }
346
347    public ConceptDefinitionComponent asConceptDefinition() {
348      return definition;
349    }
350
351    public IssueSeverity getSeverity() {
352      return severity;
353    }
354
355    public String getMessage() {
356      return message;
357    }
358
359    public boolean IsNoService() {
360      return errorClass == TerminologyServiceErrorClass.NOSERVICE;
361    }
362
363    public TerminologyServiceErrorClass getErrorClass() {
364      return errorClass;
365    }
366
367    public ValidationResult setSeverity(IssueSeverity severity) {
368      this.severity = severity;
369      return this;
370    }
371
372    public ValidationResult setMessage(String message) {
373      this.message = message;
374      return this;
375    }
376
377    public String getTxLink() {
378      return txLink;
379    }
380
381    public ValidationResult setTxLink(String txLink) {
382      this.txLink = txLink;
383      return this;
384    }
385
386  }
387
388  /**
389   * Validation of a code - consult the terminology service to see whether it is
390   * known. If known, return a description of it
391   * 
392   * note: always return a result, with either an error or a code description
393   * 
394   * corresponds to 2 terminology service calls: $validate-code and $lookup
395   * 
396   * @param system
397   * @param code
398   * @param display
399   * @return
400   */
401  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display);
402
403  /**
404   * Validation of a code - consult the terminology service to see whether it is
405   * known. If known, return a description of it Also, check whether it's in the
406   * provided value set
407   * 
408   * note: always return a result, with either an error or a code description, or
409   * both (e.g. known code, but not in the value set)
410   * 
411   * corresponds to 2 terminology service calls: $validate-code and $lookup
412   * 
413   * @param system
414   * @param code
415   * @param display
416   * @return
417   */
418  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display,
419      ValueSet vs);
420
421  public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
422
423  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
424
425  public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs);
426
427  /**
428   * Validation of a code - consult the terminology service to see whether it is
429   * known. If known, return a description of it Also, check whether it's in the
430   * provided value set fragment (for supported systems with no value set
431   * definition)
432   * 
433   * note: always return a result, with either an error or a code description, or
434   * both (e.g. known code, but not in the value set)
435   * 
436   * corresponds to 2 terminology service calls: $validate-code and $lookup
437   * 
438   * @param system
439   * @param code
440   * @param display
441   * @return
442   */
443  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display,
444      ConceptSetComponent vsi);
445
446  /**
447   * returns the recommended tla for the type
448   * 
449   * @param name
450   * @return
451   */
452  public String getAbbreviation(String name);
453
454  // return a set of types that have tails
455  public Set<String> typeTails();
456
457  public String oid2Uri(String code);
458
459  public boolean hasCache();
460
461  public interface ILoggingService {
462    public enum LogCategory {
463      PROGRESS, TX, INIT, CONTEXT, HTML
464    }
465
466    public void logMessage(String message); // status messages, always display
467
468    public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging
469  }
470
471  public void setLogger(ILoggingService logger);
472
473  public ILoggingService getLogger();
474
475  public boolean isNoTerminologyServer();
476
477  public TranslationServices translator();
478
479  public List<StructureMap> listTransforms();
480
481  public StructureMap getTransform(String url);
482
483  public String getOverrideVersionNs();
484
485  public void setOverrideVersionNs(String value);
486
487  public StructureDefinition fetchTypeDefinition(String typeName);
488
489  public void setUcumService(UcumService ucumService);
490
491  public String getLinkForUrl(String corePath, String s);
492
493  public boolean isPrimitiveType(String code);
494}