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