
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 String formatMessagePlural(Integer pl, String theMessage, Object... theMessageArguments); 303 304 void setValidationMessageLanguage(Locale locale); 305 306 public class ValidationResult { 307 private ConceptDefinitionComponent definition; 308 private IssueSeverity severity; 309 private String message; 310 private TerminologyServiceErrorClass errorClass; 311 private String txLink; 312 313 public ValidationResult(IssueSeverity severity, String message) { 314 this.severity = severity; 315 this.message = message; 316 } 317 318 public ValidationResult(ConceptDefinitionComponent definition) { 319 this.definition = definition; 320 } 321 322 public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) { 323 this.severity = severity; 324 this.message = message; 325 this.definition = definition; 326 } 327 328 public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) { 329 this.severity = severity; 330 this.message = message; 331 this.errorClass = errorClass; 332 } 333 334 public boolean isOk() { 335 return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING; 336 } 337 338 public String getDisplay() { 339// 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 340// return definition == null ? "??" : definition.getDisplay(); 341 return definition == null ? null : definition.getDisplay(); 342 } 343 344 public ConceptDefinitionComponent asConceptDefinition() { 345 return definition; 346 } 347 348 public IssueSeverity getSeverity() { 349 return severity; 350 } 351 352 public String getMessage() { 353 return message; 354 } 355 356 public boolean IsNoService() { 357 return errorClass == TerminologyServiceErrorClass.NOSERVICE; 358 } 359 360 public TerminologyServiceErrorClass getErrorClass() { 361 return errorClass; 362 } 363 364 public ValidationResult setSeverity(IssueSeverity severity) { 365 this.severity = severity; 366 return this; 367 } 368 369 public ValidationResult setMessage(String message) { 370 this.message = message; 371 return this; 372 } 373 374 public String getTxLink() { 375 return txLink; 376 } 377 378 public ValidationResult setTxLink(String txLink) { 379 this.txLink = txLink; 380 return this; 381 } 382 383 384 } 385 386 /** 387 * Validation of a code - consult the terminology service 388 * to see whether it is known. If known, return a description of it 389 * 390 * note: always return a result, with either an error or a code description 391 * 392 * corresponds to 2 terminology service calls: $validate-code and $lookup 393 * 394 * @param system 395 * @param code 396 * @param display 397 * @return 398 */ 399 public ValidationResult validateCode(ValidationOptions options, String system, String code, String display); 400 401 /** 402 * Validation of a code - consult the terminology service 403 * to see whether it is known. If known, return a description of it 404 * Also, check whether it's in the provided value set 405 * 406 * 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) 407 * 408 * corresponds to 2 terminology service calls: $validate-code and $lookup 409 * 410 * @param system 411 * @param code 412 * @param display 413 * @return 414 */ 415 public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, ValueSet vs); 416 public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs); 417 public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs); 418 public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs); 419 420 /** 421 * Validation of a code - consult the terminology service 422 * to see whether it is known. If known, return a description of it 423 * Also, check whether it's in the provided value set fragment (for supported systems with no value set definition) 424 * 425 * 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) 426 * 427 * corresponds to 2 terminology service calls: $validate-code and $lookup 428 * 429 * @param system 430 * @param code 431 * @param display 432 * @return 433 */ 434 public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, ConceptSetComponent vsi); 435 436 /** 437 * returns the recommended tla for the type 438 * 439 * @param name 440 * @return 441 */ 442 public String getAbbreviation(String name); 443 444 // return a set of types that have tails 445 public Set<String> typeTails(); 446 447 public String oid2Uri(String code); 448 449 public boolean hasCache(); 450 451 public interface ILoggingService { 452 public enum LogCategory { 453 PROGRESS, TX, INIT, CONTEXT, HTML 454 } 455 public void logMessage(String message); // status messages, always display 456 public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging 457 } 458 459 public void setLogger(ILoggingService logger); 460 public ILoggingService getLogger(); 461 462 public boolean isNoTerminologyServer(); 463 464 public TranslationServices translator(); 465 public List<StructureMap> listTransforms(); 466 public StructureMap getTransform(String url); 467 468 public String getOverrideVersionNs(); 469 public void setOverrideVersionNs(String value); 470 471 public StructureDefinition fetchTypeDefinition(String typeName); 472 473 public void setUcumService(UcumService ucumService); 474 475 public String getLinkForUrl(String corePath, String s); 476}