001package org.hl7.fhir.r4b.utils; 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 034/* 035Copyright (c) 2011+, HL7, Inc 036All rights reserved. 037 038Redistribution and use in source and binary forms, with or without modification, 039are permitted provided that the following conditions are met: 040 041 * Redistributions of source code must retain the above copyright notice, this 042 list of conditions and the following disclaimer. 043 * Redistributions in binary form must reproduce the above copyright notice, 044 this list of conditions and the following disclaimer in the documentation 045 and/or other materials provided with the distribution. 046 * Neither the name of HL7 nor the names of its contributors may be used to 047 endorse or promote products derived from this software without specific 048 prior written permission. 049 050THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 051ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 052WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 053IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 054INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 055NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 056PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 057WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 058ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 059POSSIBILITY OF SUCH DAMAGE. 060 061 */ 062 063import java.util.ArrayList; 064import java.util.HashMap; 065import java.util.Iterator; 066import java.util.List; 067import java.util.Map; 068 069import org.apache.commons.lang3.StringUtils; 070import org.fhir.ucum.Utilities; 071import org.hl7.fhir.exceptions.FHIRException; 072import org.hl7.fhir.r4b.model.Base; 073import org.hl7.fhir.r4b.model.BooleanType; 074import org.hl7.fhir.r4b.model.CanonicalResource; 075import org.hl7.fhir.r4b.model.CanonicalType; 076import org.hl7.fhir.r4b.model.CodeSystem.ConceptDefinitionComponent; 077import org.hl7.fhir.r4b.model.CodeType; 078import org.hl7.fhir.r4b.model.CodeableConcept; 079import org.hl7.fhir.r4b.model.Coding; 080import org.hl7.fhir.r4b.model.DataType; 081import org.hl7.fhir.r4b.model.DecimalType; 082import org.hl7.fhir.r4b.model.DomainResource; 083import org.hl7.fhir.r4b.model.Element; 084import org.hl7.fhir.r4b.model.ElementDefinition; 085import org.hl7.fhir.r4b.model.Extension; 086import org.hl7.fhir.r4b.model.ExtensionHelper; 087import org.hl7.fhir.r4b.model.Factory; 088import org.hl7.fhir.r4b.model.Identifier; 089import org.hl7.fhir.r4b.model.Integer64Type; 090import org.hl7.fhir.r4b.model.IntegerType; 091import org.hl7.fhir.r4b.model.MarkdownType; 092import org.hl7.fhir.r4b.model.OperationOutcome.OperationOutcomeIssueComponent; 093import org.hl7.fhir.r4b.model.PrimitiveType; 094import org.hl7.fhir.r4b.model.Property; 095import org.hl7.fhir.r4b.model.Questionnaire.QuestionnaireItemComponent; 096import org.hl7.fhir.r4b.model.Questionnaire.QuestionnaireItemType; 097import org.hl7.fhir.r4b.model.StringType; 098import org.hl7.fhir.r4b.model.UriType; 099import org.hl7.fhir.r4b.model.UrlType; 100import org.hl7.fhir.r4b.model.ValueSet.ConceptReferenceComponent; 101import org.hl7.fhir.r4b.model.ValueSet.ConceptSetComponent; 102import org.hl7.fhir.utilities.StandardsStatus; 103import org.hl7.fhir.utilities.validation.ValidationMessage; 104import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; 105import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; 106import org.hl7.fhir.utilities.validation.ValidationMessage.Source; 107 108 109public class ToolingExtensions { 110 111 // validated 112// private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid"; 113// public static final String EXT_DEPRECATED = "http://hl7.org/fhir/StructureDefinition/codesystem-deprecated"; 114 public static final String EXT_DEFINITION = "http://hl7.org/fhir/StructureDefinition/valueset-concept-definition"; 115 public static final String EXT_CS_COMMENT = "http://hl7.org/fhir/StructureDefinition/codesystem-concept-comments"; 116 public static final String EXT_VS_COMMENT = "http://hl7.org/fhir/StructureDefinition/valueset-concept-comments"; 117 public static final String EXT_CS_KEYWORD = "http://hl7.org/fhir/StructureDefinition/codesystem-keyWord"; 118 public static final String EXT_VS_KEYWORD = "http://hl7.org/fhir/StructureDefinition/valueset-keyWord"; 119 private static final String EXT_IDENTIFIER = "http://hl7.org/fhir/StructureDefinition/identifier"; 120 public static final String EXT_TRANSLATION = "http://hl7.org/fhir/StructureDefinition/translation"; 121 public static final String EXT_ISSUE_SOURCE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-source"; 122 public static final String EXT_ISSUE_LINE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-line"; 123 public static final String EXT_ISSUE_COL = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-col"; 124 public static final String EXT_DISPLAY_HINT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint"; 125 public static final String EXT_REPLACED_BY = "http://hl7.org/fhir/StructureDefinition/valueset-replacedby"; 126 public static final String EXT_REGEX = "http://hl7.org/fhir/StructureDefinition/regex"; 127 public static final String EXT_CONTROL = "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl"; 128 public static final String EXT_MINOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-minOccurs"; 129 public static final String EXT_MAXOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-maxOccurs"; 130 public static final String EXT_ALLOWEDRESOURCE = "http://hl7.org/fhir/StructureDefinition/questionnaire-allowedResource"; 131 public static final String EXT_REFERENCEFILTER = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceFilter"; 132 public static final String EXT_CODE_GENERATION_PARENT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-codegen-super"; 133 public static final String EXT_HIERARCHY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy"; 134 public static final String EXT_BEST_PRACTICE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice"; 135 public static final String EXT_BEST_PRACTICE_EXPLANATION = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation"; 136 // unregistered? 137 public static final String EXT_MAPPING_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-prefix"; 138 public static final String EXT_MAPPING_SUFFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-suffix"; 139 140// public static final String EXT_FLYOVER = "http://hl7.org/fhir/Profile/questionnaire-extensions#flyover"; 141 public static final String EXT_QTYPE = "http://hl7.org/fhir/StructureDefinition/questionnnaire-baseType"; 142// private static final String EXT_QREF = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference"; 143// private static final String EXTENSION_FILTER_ONLY = "http://www.healthintersections.com.au/fhir/Profile/metadata#expandNeedsFilter"; 144// private static final String EXT_TYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type"; 145// private static final String EXT_REFERENCE = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference"; 146 private static final String EXT_FHIRTYPE = "http://hl7.org/fhir/StructureDefinition/questionnaire-fhirType"; 147 private static final String EXT_ALLOWABLE_UNITS = "http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits"; 148 public static final String EXT_CIMI_REFERENCE = "http://hl7.org/fhir/StructureDefinition/cimi-reference"; 149 public static final String EXT_UNCLOSED = "http://hl7.org/fhir/StructureDefinition/valueset-unclosed"; 150 public static final String EXT_FMM_LEVEL = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm"; 151 public static final String EXT_FMM_SUPPORT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm-support"; 152 public static final String EXT_FMM_DERIVED = "http://hl7.org/fhir/StructureDefinition/structuredefinition-conformance-derivedFrom"; 153 public static final String EXT_SEC_CAT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category"; 154 public static final String EXT_RESOURCE_CATEGORY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-category"; 155 public static final String EXT_RESOURCE_INTERFACE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-interface"; 156 public static final String EXT_TABLE_NAME = "http://hl7.org/fhir/StructureDefinition/structuredefinition-table-name"; 157 public static final String EXT_OO_FILE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-file"; 158 public static final String EXT_WORKGROUP = "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg"; 159 public static final String EXT_STANDARDS_STATUS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status"; 160 public static final String EXT_NORMATIVE_VERSION = "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version"; 161 public static final String EXT_IGP_BASE = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-base"; 162 public static final String EXT_IGP_DEFNS = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-defns"; 163 public static final String EXT_IGP_FORMAT = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-format"; 164 public static final String EXT_IGP_SOURCE = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-source"; 165 public static final String EXT_IGP_VERSION = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-version"; 166 public static final String EXT_IGP_RESOURCES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-resource"; 167 public static final String EXT_IGP_PAGES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-pages"; 168 public static final String EXT_IGP_SPREADSHEET = "http://hl7.org/fhir/StructureDefinition/igpublisher-spreadsheet"; 169 public static final String EXT_IGP_MAPPING_CSV = "http://hl7.org/fhir/StructureDefinition/igpublisher-mapping-csv"; 170 public static final String EXT_IGP_BUNDLE = "http://hl7.org/fhir/StructureDefinition/igpublisher-bundle"; 171 public static final String EXT_IGP_RESOURCE_INFO = "http://hl7.org/fhir/tools/StructureDefinition/resource-information"; 172 public static final String EXT_IGP_CONTAINED_RESOURCE_INFO = "http://hl7.org/fhir/tools/StructureDefinition/contained-resource-information"; 173 public static final String EXT_IGP_LOADVERSION = "http://hl7.org/fhir/StructureDefinition/igpublisher-loadversion"; 174 public static final String EXT_MAX_VALUESET = "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"; 175 public static final String EXT_MIN_VALUESET = "http://hl7.org/fhir/StructureDefinition/elementdefinition-minValueSet"; 176 public static final String EXT_PROFILE_ELEMENT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-profile-element"; 177 public static final String EXT_LIST_PACKAGE = "http://hl7.org/fhir/StructureDefinition/list-packageId"; 178 public static final String EXT_MAPPING_NAME = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-name"; 179 public static final String EXT_MAPPING_TYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-type"; 180 public static final String EXT_MAPPING_CARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-cardinality"; 181 public static final String EXT_MAPPING_TGTTYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-type"; 182 public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality"; 183 public static final String EXT_PRIVATE_BASE = "http://hl7.org/fhir/tools/"; 184 public static final String EXT_ALLOWED_TYPE = "http://hl7.org/fhir/StructureDefinition/operationdefinition-allowed-type"; 185 public static final String EXT_FHIR_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type"; 186 public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type"; 187 public static final String EXT_RENDERED_VALUE = "http://hl7.org/fhir/StructureDefinition/rendered-value"; 188 public static final String EXT_OLD_CONCEPTMAP_EQUIVALENCE = "http://hl7.org/fhir/1.0/StructureDefinition/extension-ConceptMap.element.target.equivalence"; 189 public static final String EXT_EXP_TOOCOSTLY = "http://hl7.org/fhir/StructureDefinition/valueset-toocostly"; 190 public static final String EXT_MUST_SUPPORT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-type-must-support"; 191 public static final String EXT_TRANSLATABLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-translatable"; 192 public static final String EXT_PATTERN = "http://hl7.org/fhir/StructureDefinition/elementdefinition-pattern"; 193 public static final String EXT_BINDING_METHOD = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-method"; 194 public static final String EXT_XML_NAMESPACE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"; 195 public static final String EXT_XML_NAME = "http://hl7.org/fhir/StructureDefinition/elementdefinition-xml-name"; 196 public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-binding-style"; 197 public static final String EXT_BINARY_FORMAT = "http://hl7.org/fhir/StructureDefinition/implementationguide-resource-format"; 198 public static final String EXT_TARGET_ID = "http://hl7.org/fhir/StructureDefinition/targetElement"; 199 public static final String EXT_TARGET_PATH = "http://hl7.org/fhir/StructureDefinition/targetPath"; 200 public static final String EXT_VALUESET_SYSTEM = "http://hl7.org/fhir/StructureDefinition/valueset-system"; 201 202 // specific extension helpers 203 204 public static Extension makeIssueSource(Source source) { 205 Extension ex = new Extension(); 206 // todo: write this up and get it published with the pack (and handle the redirect?) 207 ex.setUrl(ToolingExtensions.EXT_ISSUE_SOURCE); 208 CodeType c = new CodeType(); 209 c.setValue(source.toString()); 210 ex.setValue(c); 211 return ex; 212 } 213 214 public static boolean hasExtension(DomainResource de, String url) { 215 return getExtension(de, url) != null; 216 } 217 218 public static boolean hasExtension(Element e, String url) { 219 return getExtension(e, url) != null; 220 } 221 222// public static void addStringExtension(DomainResource dr, String url, String content) { 223// if (!StringUtils.isBlank(content)) { 224// Extension ex = getExtension(dr, url); 225// if (ex != null) 226// ex.setValue(new StringType(content)); 227// else 228// dr.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 229// } 230// } 231 232 public static void addMarkdownExtension(DomainResource dr, String url, String content) { 233 if (!StringUtils.isBlank(content)) { 234 Extension ex = getExtension(dr, url); 235 if (ex != null) 236 ex.setValue(new StringType(content)); 237 else 238 dr.getExtension().add(Factory.newExtension(url, new MarkdownType(content), true)); 239 } 240 } 241 242 public static void addStringExtension(Element e, String url, String content) { 243 if (!StringUtils.isBlank(content)) { 244 Extension ex = getExtension(e, url); 245 if (ex != null) 246 ex.setValue(new StringType(content)); 247 else 248 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 249 } 250 } 251 252 public static void addCodeExtension(Element e, String url, String content) { 253 if (!StringUtils.isBlank(content)) { 254 Extension ex = getExtension(e, url); 255 if (ex != null) 256 ex.setValue(new CodeType(content)); 257 else 258 e.getExtension().add(Factory.newExtension(url, new CodeType(content), true)); 259 } 260 } 261 262 public static void addStringExtension(DomainResource e, String url, String content) { 263 if (!StringUtils.isBlank(content)) { 264 Extension ex = getExtension(e, url); 265 if (ex != null) 266 ex.setValue(new StringType(content)); 267 else 268 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 269 } 270 } 271 272 273 public static void addBooleanExtension(Element e, String url, boolean content) { 274 Extension ex = getExtension(e, url); 275 if (ex != null) 276 ex.setValue(new BooleanType(content)); 277 else 278 e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true)); 279 } 280 281 public static void addBooleanExtension(DomainResource e, String url, boolean content) { 282 Extension ex = getExtension(e, url); 283 if (ex != null) 284 ex.setValue(new BooleanType(content)); 285 else 286 e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true)); 287 } 288 289 public static void addIntegerExtension(DomainResource dr, String url, int value) { 290 Extension ex = getExtension(dr, url); 291 if (ex != null) 292 ex.setValue(new IntegerType(value)); 293 else 294 dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true)); 295 } 296 297 public static void addCodeExtension(DomainResource dr, String url, String value) { 298 Extension ex = getExtension(dr, url); 299 if (ex != null) 300 ex.setValue(new CodeType(value)); 301 else 302 dr.getExtension().add(Factory.newExtension(url, new CodeType(value), true)); 303 } 304 305 public static void addVSComment(ConceptSetComponent nc, String comment) { 306 if (!StringUtils.isBlank(comment)) 307 nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true)); 308 } 309 public static void addVSComment(ConceptReferenceComponent nc, String comment) { 310 if (!StringUtils.isBlank(comment)) 311 nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true)); 312 } 313 314 public static void addCSComment(ConceptDefinitionComponent nc, String comment) { 315 if (!StringUtils.isBlank(comment)) 316 nc.getExtension().add(Factory.newExtension(EXT_CS_COMMENT, Factory.newString_(comment), true)); 317 } 318 319// public static void markDeprecated(Element nc) { 320// setDeprecated(nc); 321// } 322// 323 324 public static void addDefinition(Element nc, String definition) { 325 if (!StringUtils.isBlank(definition)) 326 nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true)); 327 } 328 329 public static void addDisplayHint(Element def, String hint) { 330 if (!StringUtils.isBlank(hint)) 331 def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true)); 332 } 333 334 public static String getDisplayHint(Element def) { 335 return readStringExtension(def, EXT_DISPLAY_HINT); 336 } 337 338 public static String readStringExtension(Element c, String uri) { 339 Extension ex = ExtensionHelper.getExtension(c, uri); 340 if (ex == null) 341 return null; 342 if (ex.getValue() instanceof UriType) 343 return ((UriType) ex.getValue()).getValue(); 344 if (ex.getValue() instanceof CanonicalType) 345 return ((CanonicalType) ex.getValue()).getValue(); 346 if (ex.getValue() instanceof CodeType) 347 return ((CodeType) ex.getValue()).getValue(); 348 if (ex.getValue() instanceof IntegerType) 349 return ((IntegerType) ex.getValue()).asStringValue(); 350 if (ex.getValue() instanceof Integer64Type) 351 return ((Integer64Type) ex.getValue()).asStringValue(); 352 if (ex.getValue() instanceof DecimalType) 353 return ((DecimalType) ex.getValue()).asStringValue(); 354 if ((ex.getValue() instanceof MarkdownType)) 355 return ((MarkdownType) ex.getValue()).getValue(); 356 if ((ex.getValue() instanceof PrimitiveType)) 357 return ((PrimitiveType) ex.getValue()).primitiveValue(); 358 if (!(ex.getValue() instanceof StringType)) 359 return null; 360 return ((StringType) ex.getValue()).getValue(); 361 } 362 363 public static String readStringExtension(DomainResource c, String uri) { 364 Extension ex = getExtension(c, uri); 365 if (ex == null) 366 return null; 367 if ((ex.getValue() instanceof StringType)) 368 return ((StringType) ex.getValue()).getValue(); 369 if ((ex.getValue() instanceof UriType)) 370 return ((UriType) ex.getValue()).getValue(); 371 if (ex.getValue() instanceof CodeType) 372 return ((CodeType) ex.getValue()).getValue(); 373 if (ex.getValue() instanceof IntegerType) 374 return ((IntegerType) ex.getValue()).asStringValue(); 375 if (ex.getValue() instanceof Integer64Type) 376 return ((Integer64Type) ex.getValue()).asStringValue(); 377 if (ex.getValue() instanceof DecimalType) 378 return ((DecimalType) ex.getValue()).asStringValue(); 379 if ((ex.getValue() instanceof MarkdownType)) 380 return ((MarkdownType) ex.getValue()).getValue(); 381 return null; 382 } 383 384 @SuppressWarnings("unchecked") 385 public static PrimitiveType<DataType> readPrimitiveExtension(DomainResource c, String uri) { 386 Extension ex = getExtension(c, uri); 387 if (ex == null) 388 return null; 389 return (PrimitiveType<DataType>) ex.getValue(); 390 } 391 392 public static boolean findStringExtension(Element c, String uri) { 393 Extension ex = ExtensionHelper.getExtension(c, uri); 394 if (ex == null) 395 return false; 396 if (!(ex.getValue() instanceof StringType)) 397 return false; 398 return !StringUtils.isBlank(((StringType) ex.getValue()).getValue()); 399 } 400 401 public static Boolean readBooleanExtension(Element c, String uri) { 402 Extension ex = ExtensionHelper.getExtension(c, uri); 403 if (ex == null) 404 return null; 405 if (!(ex.getValue() instanceof BooleanType)) 406 return null; 407 return ((BooleanType) ex.getValue()).getValue(); 408 } 409 410 public static boolean findBooleanExtension(Element c, String uri) { 411 Extension ex = ExtensionHelper.getExtension(c, uri); 412 if (ex == null) 413 return false; 414 if (!(ex.getValue() instanceof BooleanType)) 415 return false; 416 return true; 417 } 418 419 public static Boolean readBooleanExtension(DomainResource c, String uri) { 420 Extension ex = ExtensionHelper.getExtension(c, uri); 421 if (ex == null) 422 return null; 423 if (!(ex.getValue() instanceof BooleanType)) 424 return null; 425 return ((BooleanType) ex.getValue()).getValue(); 426 } 427 428 public static boolean readBoolExtension(DomainResource c, String uri) { 429 Extension ex = ExtensionHelper.getExtension(c, uri); 430 if (ex == null) 431 return false; 432 if (!(ex.getValue() instanceof BooleanType)) 433 return false; 434 return ((BooleanType) ex.getValue()).getValue(); 435 } 436 437 public static boolean readBoolExtension(Element e, String uri) { 438 Extension ex = ExtensionHelper.getExtension(e, uri); 439 if (ex == null) 440 return false; 441 if (!(ex.getValue() instanceof BooleanType)) 442 return false; 443 return ((BooleanType) ex.getValue()).getValue(); 444 } 445 446 public static boolean findBooleanExtension(DomainResource c, String uri) { 447 Extension ex = ExtensionHelper.getExtension(c, uri); 448 if (ex == null) 449 return false; 450 if (!(ex.getValue() instanceof BooleanType)) 451 return false; 452 return true; 453 } 454 455 public static String getCSComment(ConceptDefinitionComponent c) { 456 return readStringExtension(c, EXT_CS_COMMENT); 457 } 458// 459// public static Boolean getDeprecated(Element c) { 460// return readBooleanExtension(c, EXT_DEPRECATED); 461// } 462 463 public static boolean hasCSComment(ConceptDefinitionComponent c) { 464 return findStringExtension(c, EXT_CS_COMMENT); 465 } 466 467// public static boolean hasDeprecated(Element c) { 468// return findBooleanExtension(c, EXT_DEPRECATED); 469// } 470 471 public static void addFlyOver(QuestionnaireItemComponent item, String text, String linkId){ 472 if (!StringUtils.isBlank(text)) { 473 QuestionnaireItemComponent display = item.addItem(); 474 display.setType(QuestionnaireItemType.DISPLAY); 475 display.setText(text); 476 display.setLinkId(linkId); 477 display.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept("flyover", "http://hl7.org/fhir/questionnaire-item-control", "Fly-over"), true)); 478 } 479 } 480 481 public static void addMin(QuestionnaireItemComponent item, int min) { 482 item.getExtension().add(Factory.newExtension(EXT_MINOCCURS, Factory.newInteger(min), true)); 483 } 484 485 public static void addMax(QuestionnaireItemComponent item, int max) { 486 item.getExtension().add(Factory.newExtension(EXT_MAXOCCURS, Factory.newInteger(max), true)); 487 } 488 489 public static void addFhirType(QuestionnaireItemComponent group, String value) { 490 group.getExtension().add(Factory.newExtension(EXT_FHIRTYPE, Factory.newString_(value), true)); 491 } 492 493 public static void addControl(QuestionnaireItemComponent group, String value) { 494 group.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept(value, "http://hl7.org/fhir/questionnaire-item-control", value), true)); 495 } 496 497 public static void addAllowedResource(QuestionnaireItemComponent group, String value) { 498 group.getExtension().add(Factory.newExtension(EXT_ALLOWEDRESOURCE, Factory.newCode(value), true)); 499 } 500 501 public static void addReferenceFilter(QuestionnaireItemComponent group, String value) { 502 group.getExtension().add(Factory.newExtension(EXT_REFERENCEFILTER, Factory.newString_(value), true)); 503 } 504 505 public static void addIdentifier(Element element, Identifier value) { 506 element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true)); 507 } 508 509 /** 510 * @param name the identity of the extension of interest 511 * @return The extension, if on this element, else null 512 */ 513 public static Extension getExtension(DomainResource resource, String name) { 514 if (name == null) 515 return null; 516 if (!resource.hasExtension()) 517 return null; 518 for (Extension e : resource.getExtension()) { 519 if (name.equals(e.getUrl())) 520 return e; 521 } 522 return null; 523 } 524 525 public static Extension getExtension(Element el, String name) { 526 if (name == null) 527 return null; 528 if (!el.hasExtension()) 529 return null; 530 for (Extension e : el.getExtension()) { 531 if (name.equals(e.getUrl())) 532 return e; 533 } 534 return null; 535 } 536 537 public static void setStringExtension(DomainResource resource, String uri, String value) { 538 if (Utilities.noString(value)) 539 return; 540 Extension ext = getExtension(resource, uri); 541 if (ext != null) 542 ext.setValue(new StringType(value)); 543 else 544 resource.getExtension().add(new Extension(uri).setValue(new StringType(value))); 545 } 546 547 public static void setStringExtension(Element resource, String uri, String value) { 548 if (Utilities.noString(value)) 549 return; 550 Extension ext = getExtension(resource, uri); 551 if (ext != null) 552 ext.setValue(new StringType(value)); 553 else 554 resource.getExtension().add(new Extension(uri).setValue(new StringType(value))); 555 } 556 557 public static void setCodeExtension(DomainResource resource, String uri, String value) { 558 if (Utilities.noString(value)) 559 return; 560 561 Extension ext = getExtension(resource, uri); 562 if (ext != null) 563 ext.setValue(new CodeType(value)); 564 else 565 resource.getExtension().add(new Extension(uri).setValue(new CodeType(value))); 566 } 567 568 public static void setCodeExtension(Element element, String uri, String value) { 569 if (Utilities.noString(value)) 570 return; 571 572 Extension ext = getExtension(element, uri); 573 if (ext != null) 574 ext.setValue(new CodeType(value)); 575 else 576 element.getExtension().add(new Extension(uri).setValue(new CodeType(value))); 577 } 578 579 public static void setIntegerExtension(DomainResource resource, String uri, int value) { 580 Extension ext = getExtension(resource, uri); 581 if (ext != null) 582 ext.setValue(new IntegerType(value)); 583 else 584 resource.getExtension().add(new Extension(uri).setValue(new IntegerType(value))); 585 } 586 587// public static String getOID(CodeSystem define) { 588// return readStringExtension(define, EXT_OID); 589// } 590// 591// public static String getOID(ValueSet vs) { 592// return readStringExtension(vs, EXT_OID); 593// } 594// 595// public static void setOID(CodeSystem define, String oid) throws FHIRFormatError, URISyntaxException { 596// if (!oid.startsWith("urn:oid:")) 597// throw new FHIRFormatError("Error in OID format"); 598// if (oid.startsWith("urn:oid:urn:oid:")) 599// throw new FHIRFormatError("Error in OID format"); 600// if (!hasExtension(define, EXT_OID)) 601// define.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false)); 602// else if (!oid.equals(readStringExtension(define, EXT_OID))) 603// throw new Error("Attempt to assign multiple OIDs to a code system"); 604// } 605// public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException { 606// if (!oid.startsWith("urn:oid:")) 607// throw new FHIRFormatError("Error in OID format"); 608// if (oid.startsWith("urn:oid:urn:oid:")) 609// throw new FHIRFormatError("Error in OID format"); 610// if (!hasExtension(vs, EXT_OID)) 611// vs.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false)); 612// else if (!oid.equals(readStringExtension(vs, EXT_OID))) 613// throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid); 614// } 615 616 public static boolean hasLanguageTranslation(Element element, String lang) { 617 for (Extension e : element.getExtension()) { 618 if (e.getUrl().equals(EXT_TRANSLATION)) { 619 Extension e1 = ExtensionHelper.getExtension(e, "lang"); 620 621 if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) 622 return true; 623 } 624 } 625 return false; 626 } 627 628 public static String getLanguageTranslation(Element element, String lang) { 629 for (Extension e : element.getExtension()) { 630 if (e.getUrl().equals(EXT_TRANSLATION)) { 631 Extension e1 = ExtensionHelper.getExtension(e, "lang"); 632 633 if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) { 634 e1 = ExtensionHelper.getExtension(e, "content"); 635 return ((StringType) e.getValue()).getValue(); 636 } 637 } 638 } 639 return null; 640 } 641 642 public static void addLanguageTranslation(Element element, String lang, String value) { 643 if (Utilities.noString(lang) || Utilities.noString(value)) 644 return; 645 646 Extension extension = new Extension().setUrl(EXT_TRANSLATION); 647 extension.addExtension().setUrl("lang").setValue(new CodeType(lang)); 648 extension.addExtension().setUrl("content").setValue(new StringType(value)); 649 element.getExtension().add(extension); 650 } 651 652 public static DataType getAllowedUnits(ElementDefinition eld) { 653 for (Extension e : eld.getExtension()) 654 if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) 655 return e.getValue(); 656 return null; 657 } 658 659 public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) { 660 for (Extension e : eld.getExtension()) 661 if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) { 662 e.setValue(cc); 663 return; 664 } 665 eld.getExtension().add(new Extension().setUrl(EXT_ALLOWABLE_UNITS).setValue(cc)); 666 } 667 668 public static List<Extension> getExtensions(Element element, String url) { 669 List<Extension> results = new ArrayList<Extension>(); 670 for (Extension ex : element.getExtension()) 671 if (ex.getUrl().equals(url)) 672 results.add(ex); 673 return results; 674 } 675 676 public static List<Extension> getExtensions(DomainResource resource, String url) { 677 List<Extension> results = new ArrayList<Extension>(); 678 for (Extension ex : resource.getExtension()) 679 if (ex.getUrl().equals(url)) 680 results.add(ex); 681 return results; 682 } 683 684// public static void addDEReference(DataElement de, String value) { 685// for (Extension e : de.getExtension()) 686// if (e.getUrl().equals(EXT_CIMI_REFERENCE)) { 687// e.setValue(new UriType(value)); 688// return; 689// } 690// de.getExtension().add(new Extension().setUrl(EXT_CIMI_REFERENCE).setValue(new UriType(value))); 691// } 692 693// public static void setDeprecated(Element nc) { 694// for (Extension e : nc.getExtension()) 695// if (e.getUrl().equals(EXT_DEPRECATED)) { 696// e.setValue(new BooleanType(true)); 697// return; 698// } 699// nc.getExtension().add(new Extension().setUrl(EXT_DEPRECATED).setValue(new BooleanType(true))); 700// } 701 702 public static void setExtension(Element focus, String url, Coding c) { 703 for (Extension e : focus.getExtension()) 704 if (e.getUrl().equals(url)) { 705 e.setValue(c); 706 return; 707 } 708 focus.getExtension().add(new Extension().setUrl(url).setValue(c)); 709 } 710 711 public static void removeExtension(DomainResource focus, String url) { 712 Iterator<Extension> i = focus.getExtension().iterator(); 713 while (i.hasNext()) { 714 Extension e = i.next(); // must be called before you can call i.remove() 715 if (e.getUrl().equals(url)) { 716 i.remove(); 717 } 718 } 719 } 720 721 public static void removeExtension(Element focus, String url) { 722 Iterator<Extension> i = focus.getExtension().iterator(); 723 while (i.hasNext()) { 724 Extension e = i.next(); // must be called before you can call i.remove() 725 if (e.getUrl().equals(url)) { 726 i.remove(); 727 } 728 } 729 } 730 731 public static int readIntegerExtension(DomainResource dr, String uri, int defaultValue) { 732 Extension ex = ExtensionHelper.getExtension(dr, uri); 733 if (ex == null) 734 return defaultValue; 735 if (ex.getValue() instanceof IntegerType) 736 return ((IntegerType) ex.getValue()).getValue(); 737 throw new Error("Unable to read extension "+uri+" as an integer"); 738 } 739 740 public static int readIntegerExtension(Element e, String uri, int defaultValue) { 741 Extension ex = ExtensionHelper.getExtension(e, uri); 742 if (ex == null) 743 return defaultValue; 744 if (ex.getValue() instanceof IntegerType) 745 return ((IntegerType) ex.getValue()).getValue(); 746 throw new Error("Unable to read extension "+uri+" as an integer"); 747 } 748 749 public static Map<String, String> getLanguageTranslations(Element e) { 750 Map<String, String> res = new HashMap<String, String>(); 751 for (Extension ext : e.getExtension()) { 752 if (ext.getUrl().equals(EXT_TRANSLATION)) { 753 String lang = readStringExtension(ext, "lang"); 754 String value = readStringExtension(ext, "content"); 755 res.put(lang, value); 756 } 757 } 758 return res; 759 } 760 761 public static StandardsStatus getStandardsStatus(DomainResource dr) throws FHIRException { 762 return StandardsStatus.fromCode(ToolingExtensions.readStringExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS)); 763 } 764 765 public static void setStandardsStatus(DomainResource dr, StandardsStatus status, String normativeVersion) { 766 if (status == null) 767 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS); 768 else 769 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS, status.toCode()); 770 if (normativeVersion == null) 771 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION); 772 else 773 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION, normativeVersion); 774 } 775 776 public static void setStandardsStatus(Element dr, StandardsStatus status, String normativeVersion) { 777 if (status == null) 778 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS); 779 else 780 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS, status.toCode()); 781 if (normativeVersion == null) 782 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION); 783 else 784 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION, normativeVersion); 785 } 786 787 public static ValidationMessage readValidationMessage(OperationOutcomeIssueComponent issue, Source source) { 788 ValidationMessage vm = new ValidationMessage(); 789 vm.setSource(source); 790 vm.setLevel(mapSeverity(issue.getSeverity())); 791 vm.setType(mapType(issue.getCode())); 792 if (issue.hasExtension(ToolingExtensions.EXT_ISSUE_LINE)) 793 vm.setLine(ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, 0)); 794 if (issue.hasExtension(ToolingExtensions.EXT_ISSUE_COL)) 795 vm.setCol(ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, 0)); 796 if (issue.hasExpression()) 797 vm.setLocation(issue.getExpression().get(0).asStringValue()); 798 vm.setMessage(issue.getDetails().getText()); 799 if (issue.hasExtension("http://hl7.org/fhir/StructureDefinition/rendering-xhtml")) 800 vm.setHtml(ToolingExtensions.readStringExtension(issue, "http://hl7.org/fhir/StructureDefinition/rendering-xhtml")); 801 return vm; 802 } 803 804 private static IssueType mapType(org.hl7.fhir.r4b.model.OperationOutcome.IssueType code) { 805 switch (code) { 806 case BUSINESSRULE: return IssueType.BUSINESSRULE; 807 case CODEINVALID: return IssueType.CODEINVALID; 808 case CONFLICT: return IssueType.CONFLICT; 809 case DELETED: return IssueType.DELETED; 810 case DUPLICATE: return IssueType.DUPLICATE; 811 case EXCEPTION: return IssueType.EXCEPTION; 812 case EXPIRED: return IssueType.EXPIRED; 813 case EXTENSION: return IssueType.EXTENSION; 814 case FORBIDDEN: return IssueType.FORBIDDEN; 815 case INCOMPLETE: return IssueType.INCOMPLETE; 816 case INFORMATIONAL: return IssueType.INFORMATIONAL; 817 case INVALID: return IssueType.INVALID; 818 case INVARIANT: return IssueType.INVARIANT; 819 case LOCKERROR: return IssueType.LOCKERROR; 820 case LOGIN: return IssueType.LOGIN; 821 case MULTIPLEMATCHES: return IssueType.MULTIPLEMATCHES; 822 case NOSTORE: return IssueType.NOSTORE; 823 case NOTFOUND: return IssueType.NOTFOUND; 824 case NOTSUPPORTED: return IssueType.NOTSUPPORTED; 825 case NULL: return IssueType.NULL; 826 case PROCESSING: return IssueType.PROCESSING; 827 case REQUIRED: return IssueType.REQUIRED; 828 case SECURITY: return IssueType.SECURITY; 829 case STRUCTURE: return IssueType.STRUCTURE; 830 case SUPPRESSED: return IssueType.SUPPRESSED; 831 case THROTTLED: return IssueType.THROTTLED; 832 case TIMEOUT: return IssueType.TIMEOUT; 833 case TOOCOSTLY: return IssueType.TOOCOSTLY; 834 case TOOLONG: return IssueType.TOOLONG; 835 case TRANSIENT: return IssueType.TRANSIENT; 836 case UNKNOWN: return IssueType.UNKNOWN; 837 case VALUE: return IssueType.VALUE; 838 default: return null; 839 } 840 } 841 842 private static IssueSeverity mapSeverity(org.hl7.fhir.r4b.model.OperationOutcome.IssueSeverity severity) { 843 switch (severity) { 844 case ERROR: return IssueSeverity.ERROR; 845 case FATAL: return IssueSeverity.FATAL; 846 case INFORMATION: return IssueSeverity.INFORMATION; 847 case WARNING: return IssueSeverity.WARNING; 848 default: return null; 849 } 850 } 851 852 public static String getPresentation(PrimitiveType<?> type) { 853 if (type.hasExtension(EXT_RENDERED_VALUE)) 854 return readStringExtension(type, EXT_RENDERED_VALUE); 855 return type.primitiveValue(); 856 } 857 858 public static String getPresentation(Element holder, PrimitiveType<?> type) { 859 if (holder.hasExtension(EXT_RENDERED_VALUE)) 860 return readStringExtension(holder, EXT_RENDERED_VALUE); 861 if (type.hasExtension(EXT_RENDERED_VALUE)) 862 return readStringExtension(type, EXT_RENDERED_VALUE); 863 return type.primitiveValue(); 864 } 865 866// public static boolean hasOID(ValueSet vs) { 867// return hasExtension(vs, EXT_OID); 868// } 869// 870// public static boolean hasOID(CodeSystem cs) { 871// return hasExtension(cs, EXT_OID); 872// } 873// 874 public static void addUrlExtension(Element e, String url, String content) { 875 if (!StringUtils.isBlank(content)) { 876 Extension ex = getExtension(e, url); 877 if (ex != null) 878 ex.setValue(new UrlType(content)); 879 else 880 e.getExtension().add(Factory.newExtension(url, new UrlType(content), true)); 881 } 882 } 883 884 public static void addUrlExtension(DomainResource dr, String url, String value) { 885 Extension ex = getExtension(dr, url); 886 if (ex != null) 887 ex.setValue(new UrlType(value)); 888 else 889 dr.getExtension().add(Factory.newExtension(url, new UrlType(value), true)); 890 } 891 892 public static void addUriExtension(Element e, String url, String content) { 893 if (!StringUtils.isBlank(content)) { 894 Extension ex = getExtension(e, url); 895 if (ex != null) 896 ex.setValue(new UriType(content)); 897 else 898 e.getExtension().add(Factory.newExtension(url, new UriType(content), true)); 899 } 900 } 901 902 public static void addUriExtension(DomainResource dr, String url, String value) { 903 Extension ex = getExtension(dr, url); 904 if (ex != null) 905 ex.setValue(new UriType(value)); 906 else 907 dr.getExtension().add(Factory.newExtension(url, new UriType(value), true)); 908 } 909 910 public static boolean usesExtension(String url, Base base) { 911 if ("Extension".equals(base.fhirType())) { 912 Property p = base.getNamedProperty("url"); 913 for (Base b : p.getValues()) { 914 if (url.equals(b.primitiveValue())) { 915 return true; 916 } 917 } 918 } 919 920 for (Property p : base.children() ) { 921 for (Base v : p.getValues()) { 922 if (usesExtension(url, v)) { 923 return true; 924 } 925 } 926 } 927 return false; 928 } 929 930 931}