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