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