001package org.hl7.fhir.dstu3.context;
002
003/*-
004 * #%L
005 * org.hl7.fhir.dstu3
006 * %%
007 * Copyright (C) 2014 - 2019 Health Level 7
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023
024import java.util.List;
025import java.util.Set;
026
027import org.hl7.fhir.dstu3.formats.IParser;
028import org.hl7.fhir.dstu3.formats.ParserType;
029import org.hl7.fhir.dstu3.model.CodeSystem;
030import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent;
031import org.hl7.fhir.dstu3.model.CodeableConcept;
032import org.hl7.fhir.dstu3.model.Coding;
033import org.hl7.fhir.dstu3.model.ConceptMap;
034import org.hl7.fhir.dstu3.model.ExpansionProfile;
035import org.hl7.fhir.dstu3.model.MetadataResource;
036import org.hl7.fhir.dstu3.model.Resource;
037import org.hl7.fhir.dstu3.model.StructureDefinition;
038import org.hl7.fhir.dstu3.model.ValueSet;
039import org.hl7.fhir.dstu3.model.ValueSet.ConceptSetComponent;
040import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionComponent;
041import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.TerminologyServiceErrorClass;
042import org.hl7.fhir.dstu3.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
043import org.hl7.fhir.dstu3.utils.INarrativeGenerator;
044import org.hl7.fhir.dstu3.utils.IResourceValidator;
045import org.hl7.fhir.exceptions.FHIRException;
046import org.hl7.fhir.exceptions.TerminologyServiceException;
047import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
048
049
050/**
051 * This is the standard interface used for access to underlying FHIR
052 * services through the tools and utilities provided by the reference
053 * implementation. 
054 * 
055 * The functionality it provides is 
056 *  - get access to parsers, validators, narrative builders etc
057 *    (you can't create these directly because they need access 
058 *    to the right context for their information)
059 *    
060 *  - find resources that the tools need to carry out their tasks
061 *  
062 *  - provide access to terminology services they need. 
063 *    (typically, these terminology service requests are just
064 *    passed through to the local implementation's terminology
065 *    service)    
066 *  
067 * @author Grahame
068 */
069public interface IWorkerContext {
070
071  /**
072   * Get the versions of the definitions loaded in context
073   * @return
074   */
075  public String getVersion();
076  
077  // -- Parsers (read and write instances) ----------------------------------------
078
079
080  /**
081   * Get a parser to read/write instances. Use the defined type (will be extended 
082   * as further types are added, though the only currently anticipate type is RDF)
083   * 
084   * XML/JSON - the standard renderers
085   * XHTML - render the narrative only (generate it if necessary)
086   * 
087   * @param type
088   * @return
089   */
090  public IParser getParser(ParserType type);
091
092  /**
093   * Get a parser to read/write instances. Determine the type 
094   * from the stated type. Supported value for type:
095   * - the recommended MIME types
096   * - variants of application/xml and application/json
097   * - _format values xml, json
098   * 
099   * @param type
100   * @return
101   */   
102  public IParser getParser(String type);
103
104  /**
105   * Get a JSON parser
106   * 
107   * @return
108   */
109  public IParser newJsonParser();
110
111  /**
112   * Get an XML parser
113   * 
114   * @return
115   */
116  public IParser newXmlParser();
117
118  /**
119   * Get a generator that can generate narrative for the instance
120   * 
121   * @return a prepared generator
122   */
123  public INarrativeGenerator getNarrativeGenerator(String prefix, String basePath);
124
125  /**
126   * Get a validator that can check whether a resource is valid 
127   * 
128   * @return a prepared generator
129   * @throws FHIRException 
130   * @
131   */
132  public IResourceValidator newValidator() throws FHIRException;
133
134  // -- resource fetchers ---------------------------------------------------
135
136  /**
137   * Find an identified resource. The most common use of this is to access the the 
138   * standard conformance resources that are part of the standard - structure 
139   * definitions, value sets, concept maps, etc.
140   * 
141   * Also, the narrative generator uses this, and may access any kind of resource
142   * 
143   * The URI is called speculatively for things that might exist, so not finding 
144   * a matching resouce, return null, not an error
145   * 
146   * The URI can have one of 3 formats:
147   *  - a full URL e.g. http://acme.org/fhir/ValueSet/[id]
148   *  - a relative URL e.g. ValueSet/[id]
149   *  - a logical id e.g. [id]
150   *  
151   * It's an error if the second form doesn't agree with class_. It's an 
152   * error if class_ is null for the last form
153   * 
154   * @param resource
155   * @param Reference
156   * @return
157   * @throws FHIRException 
158   * @throws Exception
159   */
160  public <T extends Resource> T fetchResource(Class<T> class_, String uri);
161  public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
162
163  /**
164   * find whether a resource is available. 
165   * 
166   * Implementations of the interface can assume that if hasResource ruturns 
167   * true, the resource will usually be fetched subsequently
168   * 
169   * @param class_
170   * @param uri
171   * @return
172   */
173  public <T extends Resource> boolean hasResource(Class<T> class_, String uri);
174
175  // -- profile services ---------------------------------------------------------
176  
177  public List<String> getResourceNames();
178  public Set<String> getResourceNamesAsSet();
179  public List<String> getTypeNames();
180  public List<StructureDefinition> allStructures();
181  public List<MetadataResource> allConformanceResources();
182  
183  // -- Terminology services ------------------------------------------------------
184
185  public ExpansionProfile getExpansionProfile();
186  public void setExpansionProfile(ExpansionProfile expProfile);
187
188  // these are the terminology services used internally by the tools
189  /**
190   * Find the code system definition for the nominated system uri. 
191   * return null if there isn't one (then the tool might try 
192   * supportsSystem)
193   * 
194   * @param system
195   * @return
196   */
197  public CodeSystem fetchCodeSystem(String system);
198
199  /**
200   * True if the underlying terminology service provider will do 
201   * expansion and code validation for the terminology. Corresponds
202   * to the extension 
203   * 
204   * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system
205   * 
206   * in the Conformance resource
207   * 
208   * @param system
209   * @return
210   * @throws Exception 
211   */
212  public boolean supportsSystem(String system) throws TerminologyServiceException;
213
214  /**
215   * find concept maps for a source
216   * @param url
217   * @return
218   */
219  public List<ConceptMap> findMapsForSource(String url);  
220
221  /**
222   * ValueSet Expansion - see $expand
223   *  
224   * @param source
225   * @return
226   */
227  public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
228  
229  /**
230   * Value set expanion inside the internal expansion engine - used 
231   * for references to supported system (see "supportsSystem") for
232   * which there is no value set. 
233   * 
234   * @param inc
235   * @return
236   * @throws FHIRException 
237   */
238  public ValueSetExpansionComponent expandVS(ConceptSetComponent inc, boolean heiarchical) throws TerminologyServiceException;
239  
240  public class ValidationResult {
241    private ConceptDefinitionComponent definition;
242    private IssueSeverity severity;
243    private String message;
244    private TerminologyServiceErrorClass errorClass;
245    
246    public ValidationResult(IssueSeverity severity, String message) {
247      this.severity = severity;
248      this.message = message;
249    }
250    
251    public ValidationResult(ConceptDefinitionComponent definition) {
252      this.definition = definition;
253    }
254
255    public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) {
256      this.severity = severity;
257      this.message = message;
258      this.definition = definition;
259    }
260    
261    public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
262      this.severity = severity;
263      this.message = message;
264      this.errorClass = errorClass;
265    }
266
267    public boolean isOk() {
268      return definition != null;
269    }
270
271    public String getDisplay() {
272// 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
273//      return definition == null ? "??" : definition.getDisplay();
274      return definition == null ? null : definition.getDisplay();
275    }
276
277    public ConceptDefinitionComponent asConceptDefinition() {
278      return definition;
279    }
280
281    public IssueSeverity getSeverity() {
282      return severity;
283    }
284
285    public String getMessage() {
286      return message;
287    }
288
289    public boolean IsNoService() {
290      return errorClass == TerminologyServiceErrorClass.NOSERVICE;
291    }
292
293    public TerminologyServiceErrorClass getErrorClass() {
294      return errorClass;
295    }
296    
297    
298  }
299
300  /**
301   * Validation of a code - consult the terminology service 
302   * to see whether it is known. If known, return a description of it
303   * 
304   *  note: always return a result, with either an error or a code description
305   *  
306   * corresponds to 2 terminology service calls: $validate-code and $lookup
307   * 
308   * @param system
309   * @param code
310   * @param display
311   * @return
312   */
313  public ValidationResult validateCode(String system, String code, String display);
314
315  /**
316   * Validation of a code - consult the terminology service 
317   * to see whether it is known. If known, return a description of it
318   * Also, check whether it's in the provided value set
319   * 
320   * 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)
321   *  
322   * corresponds to 2 terminology service calls: $validate-code and $lookup
323   * 
324   * @param system
325   * @param code
326   * @param display
327   * @return
328   */
329  public ValidationResult validateCode(String system, String code, String display, ValueSet vs);
330  public ValidationResult validateCode(Coding code, ValueSet vs);
331  public ValidationResult validateCode(CodeableConcept code, ValueSet vs);
332  
333  /**
334   * Validation of a code - consult the terminology service 
335   * to see whether it is known. If known, return a description of it
336   * Also, check whether it's in the provided value set fragment (for supported systems with no value set definition)
337   * 
338   * 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)
339   *  
340   * corresponds to 2 terminology service calls: $validate-code and $lookup
341   * 
342   * @param system
343   * @param code
344   * @param display
345   * @return
346   */
347  public ValidationResult validateCode(String system, String code, String display, ConceptSetComponent vsi);
348
349  /**
350   * returns the recommended tla for the type 
351   * 
352   * @param name
353   * @return
354   */
355  public String getAbbreviation(String name);
356
357  // return a set of types that have tails
358  public Set<String> typeTails();
359
360        public String oid2Uri(String code);
361
362  public boolean hasCache();
363
364  public interface ILoggingService {
365    public enum LogCategory {
366      PROGRESS, TX, INIT, CONTEXT, HTML 
367    }
368    public void logMessage(String message); // status messages, always display
369    public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging 
370  }
371
372  public void setLogger(ILoggingService logger);
373
374  public boolean isNoTerminologyServer();
375  public StructureDefinition fetchTypeDefinition(String typeName);
376
377}