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    public Parameters getOrMakeParameters() {
391        Parameters p = new Parameters();
392        p.addParameter("result", isOk());
393        if (getMessage() != null) {
394          p.addParameter("message", getMessage());
395        }
396        if (getDisplay() != null) {
397          p.addParameter("display", getDisplay());
398        }
399        return p;
400    }
401  }
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
406   * 
407   * note: always return a result, with either an error or a code description
408   * 
409   * corresponds to 2 terminology service calls: $validate-code and $lookup
410   * 
411   * @param system
412   * @param code
413   * @param display
414   * @return
415   */
416  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display);
417
418  /**
419   * Validation of a code - consult the terminology service to see whether it is
420   * known. If known, return a description of it Also, check whether it's in the
421   * provided value set
422   * 
423   * note: always return a result, with either an error or a code description, or
424   * both (e.g. known code, but not in the value set)
425   * 
426   * corresponds to 2 terminology service calls: $validate-code and $lookup
427   * 
428   * @param system
429   * @param code
430   * @param display
431   * @return
432   */
433  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display,
434      ValueSet vs);
435
436  public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
437
438  public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
439
440  public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs);
441
442  /**
443   * Validation of a code - consult the terminology service to see whether it is
444   * known. If known, return a description of it Also, check whether it's in the
445   * provided value set fragment (for supported systems with no value set
446   * definition)
447   * 
448   * note: always return a result, with either an error or a code description, or
449   * both (e.g. known code, but not in the value set)
450   * 
451   * corresponds to 2 terminology service calls: $validate-code and $lookup
452   * 
453   * @param system
454   * @param code
455   * @param display
456   * @return
457   */
458  public ValidationResult validateCode(ValidationOptions options, String system, String code, String display,
459      ConceptSetComponent vsi);
460
461  /**
462   * returns the recommended tla for the type
463   * 
464   * @param name
465   * @return
466   */
467  public String getAbbreviation(String name);
468
469  // return a set of types that have tails
470  public Set<String> typeTails();
471
472  public String oid2Uri(String code);
473
474  public boolean hasCache();
475
476  public interface ILoggingService {
477    public enum LogCategory {
478      PROGRESS, TX, INIT, CONTEXT, HTML
479    }
480
481    public void logMessage(String message); // status messages, always display
482
483    public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging
484  }
485
486  public void setLogger(ILoggingService logger);
487
488  public ILoggingService getLogger();
489
490  public boolean isNoTerminologyServer();
491
492  public TranslationServices translator();
493
494  public List<StructureMap> listTransforms();
495
496  public StructureMap getTransform(String url);
497
498  public String getOverrideVersionNs();
499
500  public void setOverrideVersionNs(String value);
501
502  public StructureDefinition fetchTypeDefinition(String typeName);
503  public List<StructureDefinition> fetchTypeDefinitions(String n);
504
505  public void setUcumService(UcumService ucumService);
506
507  public String getLinkForUrl(String corePath, String s);
508
509  public boolean isPrimitiveType(String code);
510}