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