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