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 172 public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException; 173 174 /** 175 * Variation of fetchResource when you have a string type, and don't need the 176 * right class 177 * 178 * The URI can have one of 3 formats: - a full URL e.g. 179 * http://acme.org/fhir/ValueSet/[id] - a relative URL e.g. ValueSet/[id] - a 180 * logical id e.g. [id] 181 * 182 * if type == null, the URI can't be a simple logical id 183 * 184 * @param type 185 * @param uri 186 * @return 187 */ 188 public Resource fetchResourceById(String type, String uri); 189 190 /** 191 * find whether a resource is available. 192 * 193 * Implementations of the interface can assume that if hasResource ruturns true, 194 * the resource will usually be fetched subsequently 195 * 196 * @param class_ 197 * @param uri 198 * @return 199 */ 200 public <T extends Resource> boolean hasResource(Class<T> class_, String uri); 201 202 /** 203 * cache a resource for later retrieval using fetchResource. 204 * 205 * Note that various context implementations will have their own ways of loading 206 * rseources, and not all need implement cacheResource 207 * 208 * @param res 209 * @throws FHIRException 210 */ 211 public void cacheResource(Resource res) throws FHIRException; 212 213 // -- profile services --------------------------------------------------------- 214 215 public List<String> getResourceNames(); 216 217 public Set<String> getResourceNamesAsSet(); 218 219 public List<String> getTypeNames(); 220 221 public List<StructureDefinition> allStructures(); // ensure snapshot exists... 222 223 public List<StructureDefinition> getStructures(); 224 225 public List<MetadataResource> allConformanceResources(); 226 227 public void generateSnapshot(StructureDefinition p) throws DefinitionException, FHIRException; 228 229 // -- Terminology services 230 // ------------------------------------------------------ 231 232 public Parameters getExpansionParameters(); 233 234 public void setExpansionProfile(Parameters expParameters); 235 236 // these are the terminology services used internally by the tools 237 /** 238 * Find the code system definition for the nominated system uri. return null if 239 * there isn't one (then the tool might try 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 expansion and 248 * code validation for the terminology. Corresponds to the extension 249 * 250 * http://hl7.org/fhir/StructureDefinition/capabilitystatement-supported-system 251 * 252 * in the Conformance resource 253 * 254 * @param system 255 * @return 256 * @throws Exception 257 */ 258 public boolean supportsSystem(String system) throws TerminologyServiceException; 259 260 /** 261 * find concept maps for a source 262 * 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, 285 boolean heiarchical) throws FHIRException; 286 287 /** 288 * Value set expanion inside the internal expansion engine - used for references 289 * to supported system (see "supportsSystem") for which there is no value set. 290 * 291 * @param inc 292 * @return 293 * @throws FHIRException 294 */ 295 public ValueSetExpansionOutcome expandVS(ConceptSetComponent inc, boolean heirarchical) 296 throws TerminologyServiceException; 297 298 Locale getLocale(); 299 300 void setLocale(Locale locale); 301 302 String formatMessage(String theMessage, Object... theMessageArguments); 303 304 String formatMessagePlural(Integer pl, String theMessage, Object... theMessageArguments); 305 306 void setValidationMessageLanguage(Locale locale); 307 308 public class ValidationResult { 309 private ConceptDefinitionComponent definition; 310 private IssueSeverity severity; 311 private String message; 312 private TerminologyServiceErrorClass errorClass; 313 private String txLink; 314 315 public ValidationResult(IssueSeverity severity, String message) { 316 this.severity = severity; 317 this.message = message; 318 } 319 320 public ValidationResult(ConceptDefinitionComponent definition) { 321 this.definition = definition; 322 } 323 324 public ValidationResult(IssueSeverity severity, String message, ConceptDefinitionComponent definition) { 325 this.severity = severity; 326 this.message = message; 327 this.definition = definition; 328 } 329 330 public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) { 331 this.severity = severity; 332 this.message = message; 333 this.errorClass = errorClass; 334 } 335 336 public boolean isOk() { 337 return severity == null || severity == IssueSeverity.INFORMATION || severity == IssueSeverity.WARNING; 338 } 339 340 public String getDisplay() { 341// 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 342// return definition == null ? "??" : definition.getDisplay(); 343 return definition == null ? null : definition.getDisplay(); 344 } 345 346 public ConceptDefinitionComponent asConceptDefinition() { 347 return definition; 348 } 349 350 public IssueSeverity getSeverity() { 351 return severity; 352 } 353 354 public String getMessage() { 355 return message; 356 } 357 358 public boolean IsNoService() { 359 return errorClass == TerminologyServiceErrorClass.NOSERVICE; 360 } 361 362 public TerminologyServiceErrorClass getErrorClass() { 363 return errorClass; 364 } 365 366 public ValidationResult setSeverity(IssueSeverity severity) { 367 this.severity = severity; 368 return this; 369 } 370 371 public ValidationResult setMessage(String message) { 372 this.message = message; 373 return this; 374 } 375 376 public String getTxLink() { 377 return txLink; 378 } 379 380 public ValidationResult setTxLink(String txLink) { 381 this.txLink = txLink; 382 return this; 383 } 384 385 } 386 387 /** 388 * Validation of a code - consult the terminology service to see whether it is 389 * known. If known, return a description of it 390 * 391 * note: always return a result, with either an error or a code description 392 * 393 * corresponds to 2 terminology service calls: $validate-code and $lookup 394 * 395 * @param system 396 * @param code 397 * @param display 398 * @return 399 */ 400 public ValidationResult validateCode(ValidationOptions options, String system, String code, String display); 401 402 /** 403 * Validation of a code - consult the terminology service to see whether it is 404 * known. If known, return a description of it Also, check whether it's in the 405 * provided value set 406 * 407 * note: always return a result, with either an error or a code description, or 408 * both (e.g. known code, but not in the value set) 409 * 410 * corresponds to 2 terminology service calls: $validate-code and $lookup 411 * 412 * @param system 413 * @param code 414 * @param display 415 * @return 416 */ 417 public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, 418 ValueSet vs); 419 420 public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs); 421 422 public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs); 423 424 public ValidationResult validateCode(ValidationOptions options, CodeableConcept code, ValueSet vs); 425 426 /** 427 * Validation of a code - consult the terminology service to see whether it is 428 * known. If known, return a description of it Also, check whether it's in the 429 * provided value set fragment (for supported systems with no value set 430 * definition) 431 * 432 * note: always return a result, with either an error or a code description, or 433 * both (e.g. known code, but not in the value set) 434 * 435 * corresponds to 2 terminology service calls: $validate-code and $lookup 436 * 437 * @param system 438 * @param code 439 * @param display 440 * @return 441 */ 442 public ValidationResult validateCode(ValidationOptions options, String system, String code, String display, 443 ConceptSetComponent vsi); 444 445 /** 446 * returns the recommended tla for the type 447 * 448 * @param name 449 * @return 450 */ 451 public String getAbbreviation(String name); 452 453 // return a set of types that have tails 454 public Set<String> typeTails(); 455 456 public String oid2Uri(String code); 457 458 public boolean hasCache(); 459 460 public interface ILoggingService { 461 public enum LogCategory { 462 PROGRESS, TX, INIT, CONTEXT, HTML 463 } 464 465 public void logMessage(String message); // status messages, always display 466 467 public void logDebugMessage(LogCategory category, String message); // verbose; only when debugging 468 } 469 470 public void setLogger(ILoggingService logger); 471 472 public ILoggingService getLogger(); 473 474 public boolean isNoTerminologyServer(); 475 476 public TranslationServices translator(); 477 478 public List<StructureMap> listTransforms(); 479 480 public StructureMap getTransform(String url); 481 482 public String getOverrideVersionNs(); 483 484 public void setOverrideVersionNs(String value); 485 486 public StructureDefinition fetchTypeDefinition(String typeName); 487 488 public void setUcumService(UcumService ucumService); 489 490 public String getLinkForUrl(String corePath, String s); 491}