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