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