001package org.hl7.fhir.r4.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/* 033Copyright (c) 2011+, HL7, Inc 034All rights reserved. 035 036Redistribution and use in source and binary forms, with or without modification, 037are permitted provided that the following conditions are met: 038 039 * Redistributions of source code must retain the above copyright notice, this 040 list of conditions and the following disclaimer. 041 * Redistributions in binary form must reproduce the above copyright notice, 042 this list of conditions and the following disclaimer in the documentation 043 and/or other materials provided with the distribution. 044 * Neither the name of HL7 nor the names of its contributors may be used to 045 endorse or promote products derived from this software without specific 046 prior written permission. 047 048THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 049ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 050WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 051IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 052INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 053NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 054PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 055WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 056ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 057POSSIBILITY OF SUCH DAMAGE. 058 059 */ 060 061import java.util.ArrayList; 062import java.util.HashMap; 063import java.util.Iterator; 064import java.util.List; 065import java.util.Map; 066 067import org.apache.commons.lang3.StringUtils; 068import org.fhir.ucum.Utilities; 069import org.hl7.fhir.exceptions.FHIRException; 070import org.hl7.fhir.r4.model.BooleanType; 071import org.hl7.fhir.r4.model.CanonicalType; 072import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; 073import org.hl7.fhir.r4.model.CodeType; 074import org.hl7.fhir.r4.model.CodeableConcept; 075import org.hl7.fhir.r4.model.Coding; 076import org.hl7.fhir.r4.model.DomainResource; 077import org.hl7.fhir.r4.model.Element; 078import org.hl7.fhir.r4.model.ElementDefinition; 079import org.hl7.fhir.r4.model.Extension; 080import org.hl7.fhir.r4.model.ExtensionHelper; 081import org.hl7.fhir.r4.model.Factory; 082import org.hl7.fhir.r4.model.Identifier; 083import org.hl7.fhir.r4.model.IntegerType; 084import org.hl7.fhir.r4.model.MarkdownType; 085import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent; 086import org.hl7.fhir.r4.model.PrimitiveType; 087import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemComponent; 088import org.hl7.fhir.r4.model.Questionnaire.QuestionnaireItemType; 089import org.hl7.fhir.r4.model.StringType; 090import org.hl7.fhir.r4.model.Type; 091import org.hl7.fhir.r4.model.UriType; 092import org.hl7.fhir.r4.model.UrlType; 093import org.hl7.fhir.r4.model.ValueSet.ConceptReferenceComponent; 094import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent; 095import org.hl7.fhir.r4.model.BackboneElement; 096import org.hl7.fhir.utilities.StandardsStatus; 097import org.hl7.fhir.utilities.validation.ValidationMessage; 098import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity; 099import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType; 100import org.hl7.fhir.utilities.validation.ValidationMessage.Source; 101 102public class ToolingExtensions { 103 104 // validated 105// private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid"; 106// public static final String EXT_DEPRECATED = "http://hl7.org/fhir/StructureDefinition/codesystem-deprecated"; 107 public static final String EXT_DEFINITION = "http://hl7.org/fhir/StructureDefinition/valueset-concept-definition"; 108 public static final String EXT_CS_COMMENT = "http://hl7.org/fhir/StructureDefinition/codesystem-concept-comments"; 109 public static final String EXT_VS_COMMENT = "http://hl7.org/fhir/StructureDefinition/valueset-concept-comments"; 110 private static final String EXT_IDENTIFIER = "http://hl7.org/fhir/StructureDefinition/identifier"; 111 public static final String EXT_TRANSLATION = "http://hl7.org/fhir/StructureDefinition/translation"; 112 public static final String EXT_ISSUE_SOURCE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-source"; 113 public static final String EXT_ISSUE_LINE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-line"; 114 public static final String EXT_ISSUE_COL = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-col"; 115 public static final String EXT_DISPLAY_HINT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint"; 116 public static final String EXT_REPLACED_BY = "http://hl7.org/fhir/StructureDefinition/valueset-replacedby"; 117 public static final String EXT_REGEX = "http://hl7.org/fhir/StructureDefinition/regex"; 118 public static final String EXT_CONTROL = "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl"; 119 public static final String EXT_MINOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-minOccurs"; 120 public static final String EXT_MAXOCCURS = "http://hl7.org/fhir/StructureDefinition/questionnaire-maxOccurs"; 121 public static final String EXT_ALLOWEDRESOURCE = "http://hl7.org/fhir/StructureDefinition/questionnaire-allowedResource"; 122 public static final String EXT_REFERENCEFILTER = "http://hl7.org/fhir/StructureDefinition/questionnaire-referenceFilter"; 123 public static final String EXT_CODE_GENERATION_PARENT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-codegen-super"; 124 public static final String EXT_HIERARCHY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-hierarchy"; 125 public static final String EXT_BEST_PRACTICE = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice"; 126 public static final String EXT_BEST_PRACTICE_EXPLANATION = "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice-explanation"; 127 // unregistered? 128 public static final String EXT_MAPPING_PREFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-prefix"; 129 public static final String EXT_MAPPING_SUFFIX = "http://hl7.org/fhir/tools/StructureDefinition/logical-mapping-suffix"; 130 131// public static final String EXT_FLYOVER = "http://hl7.org/fhir/Profile/questionnaire-extensions#flyover"; 132 public static final String EXT_QTYPE = "http://hl7.org/fhir/StructureDefinition/questionnnaire-baseType"; 133// private static final String EXT_QREF = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference"; 134// private static final String EXTENSION_FILTER_ONLY = "http://www.healthintersections.com.au/fhir/Profile/metadata#expandNeedsFilter"; 135// private static final String EXT_TYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type"; 136// private static final String EXT_REFERENCE = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference"; 137 private static final String EXT_FHIRTYPE = "http://hl7.org/fhir/StructureDefinition/questionnaire-fhirType"; 138 private static final String EXT_ALLOWABLE_UNITS = "http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits"; 139 public static final String EXT_CIMI_REFERENCE = "http://hl7.org/fhir/StructureDefinition/cimi-reference"; 140 public static final String EXT_UNCLOSED = "http://hl7.org/fhir/StructureDefinition/valueset-unclosed"; 141 public static final String EXT_FMM_LEVEL = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm"; 142 public static final String EXT_SEC_CAT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category"; 143 public static final String EXT_RESOURCE_CATEGORY = "http://hl7.org/fhir/StructureDefinition/structuredefinition-category"; 144 public static final String EXT_TABLE_NAME = "http://hl7.org/fhir/StructureDefinition/structuredefinition-table-name"; 145 public static final String EXT_OO_FILE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-file"; 146 public static final String EXT_WORKGROUP = "http://hl7.org/fhir/StructureDefinition/structuredefinition-wg"; 147 public static final String EXT_STANDARDS_STATUS = "http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status"; 148 public static final String EXT_NORMATIVE_VERSION = "http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version"; 149 public static final String EXT_IGP_BASE = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-base"; 150 public static final String EXT_IGP_DEFNS = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-defns"; 151 public static final String EXT_IGP_FORMAT = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-format"; 152 public static final String EXT_IGP_SOURCE = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-source"; 153 public static final String EXT_IGP_VERSION = "http://hl7.org/fhir/StructureDefinition/igpublisher-res-version"; 154 public static final String EXT_IGP_RESOURCES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-resource"; 155 public static final String EXT_IGP_PAGES = "http://hl7.org/fhir/StructureDefinition/igpublisher-folder-pages"; 156 public static final String EXT_IGP_SPREADSHEET = "http://hl7.org/fhir/tools/StructureDefinition/igpublisher-spreadsheet"; 157 public static final String EXT_IGP_MAPPING_CSV = "http://hl7.org/fhir/StructureDefinition/igpublisher-mapping-csv"; 158 public static final String EXT_IGP_BUNDLE = "http://hl7.org/fhir/StructureDefinition/igpublisher-bundle"; 159 public static final String EXT_IGP_RESOURCE_INFO = "http://hl7.org/fhir/tools/StructureDefinition/resource-information"; 160 public static final String EXT_IGP_LOADVERSION = "http://hl7.org/fhir/StructureDefinition/igpublisher-loadversion"; 161 public static final String EXT_MAX_VALUESET = "http://hl7.org/fhir/StructureDefinition/elementdefinition-maxValueSet"; 162 public static final String EXT_MIN_VALUESET = "http://hl7.org/fhir/StructureDefinition/elementdefinition-minValueSet"; 163 public static final String EXT_PROFILE_ELEMENT = "http://hl7.org/fhir/StructureDefinition/elementdefinition-profile-element"; 164 public static final String EXT_LIST_PACKAGE = "http://hl7.org/fhir/StructureDefinition/list-packageId"; 165 public static final String EXT_MAPPING_NAME = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-name"; 166 public static final String EXT_MAPPING_TYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-type"; 167 public static final String EXT_MAPPING_CARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-source-cardinality"; 168 public static final String EXT_MAPPING_TGTTYPE = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-type"; 169 public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality"; 170 public static final String EXT_PRIVATE_BASE = "http://hl7.org/fhir/tools/"; 171 public static final String EXT_ALLOWED_TYPE = "http://hl7.org/fhir/StructureDefinition/operationdefinition-allowed-type"; 172 public static final String EXT_FHIR_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type"; 173 public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type"; 174 public static final String EXT_JSON_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type"; 175 176 public static final String EXT_ORIGINAL_ITEM_TYPE = "http://hl7.org/fhir/4.0/StructureDefinition/extension-Questionnaire.item.type"; 177 public static final String EXT_ORIGINAL_VARIABLE_TYPE = "http://hl7.org/fhir/5.0/StructureDefinition/extension-StructureMap.group.rule.dependent.parameter"; 178 179 // specific extension helpers 180 181 public static Extension makeIssueSource(Source source) { 182 Extension ex = new Extension(); 183 // todo: write this up and get it published with the pack (and handle the 184 // redirect?) 185 ex.setUrl(ToolingExtensions.EXT_ISSUE_SOURCE); 186 CodeType c = new CodeType(); 187 c.setValue(source.toString()); 188 ex.setValue(c); 189 return ex; 190 } 191 192 public static boolean hasExtension(DomainResource de, String url) { 193 return getExtension(de, url) != null; 194 } 195 196 public static boolean hasExtension(Element e, String url) { 197 return getExtension(e, url) != null; 198 } 199 200// public static void addStringExtension(DomainResource dr, String url, String content) { 201// if (!StringUtils.isBlank(content)) { 202// Extension ex = getExtension(dr, url); 203// if (ex != null) 204// ex.setValue(new StringType(content)); 205// else 206// dr.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 207// } 208// } 209 210 public static void addMarkdownExtension(DomainResource dr, String url, String content) { 211 if (!StringUtils.isBlank(content)) { 212 Extension ex = getExtension(dr, url); 213 if (ex != null) 214 ex.setValue(new StringType(content)); 215 else 216 dr.getExtension().add(Factory.newExtension(url, new MarkdownType(content), true)); 217 } 218 } 219 220 public static void addStringExtension(Element e, String url, String content) { 221 if (!StringUtils.isBlank(content)) { 222 Extension ex = getExtension(e, url); 223 if (ex != null) 224 ex.setValue(new StringType(content)); 225 else 226 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 227 } 228 } 229 230 public static void addCodeExtension(Element e, String url, String content) { 231 if (!StringUtils.isBlank(content)) { 232 Extension ex = getExtension(e, url); 233 if (ex != null) 234 ex.setValue(new CodeType(content)); 235 else 236 e.getExtension().add(Factory.newExtension(url, new CodeType(content), true)); 237 } 238 } 239 240 public static void addStringExtension(DomainResource e, String url, String content) { 241 if (!StringUtils.isBlank(content)) { 242 Extension ex = getExtension(e, url); 243 if (ex != null) 244 ex.setValue(new StringType(content)); 245 else 246 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 247 } 248 } 249 250 public static void addUrlExtension(Element e, String url, String value) { 251 Extension ex = getExtension(e, url); 252 if (ex != null) 253 ex.setValue(new UrlType(value)); 254 else 255 e.getExtension().add(Factory.newExtension(url, new UrlType(value), true)); 256 } 257 258 public static void addUriExtension(Element e, String url, String uri) { 259 Extension ex = getExtension(e, url); 260 if (ex != null) 261 ex.setValue(new UriType(uri)); 262 else 263 e.getExtension().add(Factory.newExtension(url, new UriType(uri), true)); 264 } 265 266 public static void addBooleanExtension(Element e, String url, boolean content) { 267 Extension ex = getExtension(e, url); 268 if (ex != null) 269 ex.setValue(new BooleanType(content)); 270 else 271 e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true)); 272 } 273 274 public static void addBooleanExtension(DomainResource e, String url, boolean content) { 275 Extension ex = getExtension(e, url); 276 if (ex != null) 277 ex.setValue(new BooleanType(content)); 278 else 279 e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true)); 280 } 281 282 public static void addIntegerExtension(DomainResource dr, String url, int value) { 283 Extension ex = getExtension(dr, url); 284 if (ex != null) 285 ex.setValue(new IntegerType(value)); 286 else 287 dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true)); 288 } 289 290 public static void addCodeExtension(DomainResource dr, String url, String value) { 291 Extension ex = getExtension(dr, url); 292 if (ex != null) 293 ex.setValue(new CodeType(value)); 294 else 295 dr.getExtension().add(Factory.newExtension(url, new CodeType(value), true)); 296 } 297 298 public static void addVSComment(ConceptSetComponent nc, String comment) { 299 if (!StringUtils.isBlank(comment)) 300 nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true)); 301 } 302 303 public static void addVSComment(ConceptReferenceComponent nc, String comment) { 304 if (!StringUtils.isBlank(comment)) 305 nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true)); 306 } 307 308 public static void addCSComment(ConceptDefinitionComponent nc, String comment) { 309 if (!StringUtils.isBlank(comment)) 310 nc.getExtension().add(Factory.newExtension(EXT_CS_COMMENT, Factory.newString_(comment), true)); 311 } 312 313// public static void markDeprecated(Element nc) { 314// setDeprecated(nc); 315// } 316// 317 318 public static void addDefinition(Element nc, String definition) { 319 if (!StringUtils.isBlank(definition)) 320 nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true)); 321 } 322 323 public static void addDisplayHint(Element def, String hint) { 324 if (!StringUtils.isBlank(hint)) 325 def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true)); 326 } 327 328 public static String getDisplayHint(Element def) { 329 return readStringExtension(def, EXT_DISPLAY_HINT); 330 } 331 332 public static String readStringExtension(Element c, String uri) { 333 Extension ex = ExtensionHelper.getExtension(c, uri); 334 if (ex == null) 335 return null; 336 if (ex.getValue() instanceof UriType) 337 return ((UriType) ex.getValue()).getValue(); 338 if (ex.getValue() instanceof CanonicalType) 339 return ((CanonicalType) ex.getValue()).getValue(); 340 if (ex.getValue() instanceof CodeType) 341 return ((CodeType) ex.getValue()).getValue(); 342 if (ex.getValue() instanceof IntegerType) 343 return ((IntegerType) ex.getValue()).asStringValue(); 344 if ((ex.getValue() instanceof MarkdownType)) 345 return ((MarkdownType) ex.getValue()).getValue(); 346 if (!(ex.getValue() instanceof StringType)) 347 return null; 348 return ((StringType) ex.getValue()).getValue(); 349 } 350 351 public static String readStringExtension(DomainResource c, String uri) { 352 Extension ex = getExtension(c, uri); 353 if (ex == null) 354 return null; 355 if ((ex.getValue() instanceof StringType)) 356 return ((StringType) ex.getValue()).getValue(); 357 if ((ex.getValue() instanceof UriType)) 358 return ((UriType) ex.getValue()).getValue(); 359 if (ex.getValue() instanceof CodeType) 360 return ((CodeType) ex.getValue()).getValue(); 361 if (ex.getValue() instanceof IntegerType) 362 return ((IntegerType) ex.getValue()).asStringValue(); 363 if ((ex.getValue() instanceof MarkdownType)) 364 return ((MarkdownType) ex.getValue()).getValue(); 365 return null; 366 } 367 368 @SuppressWarnings("unchecked") 369 public static PrimitiveType<Type> readPrimitiveExtension(DomainResource c, String uri) { 370 Extension ex = getExtension(c, uri); 371 if (ex == null) 372 return null; 373 return (PrimitiveType<Type>) ex.getValue(); 374 } 375 376 public static boolean findStringExtension(Element c, String uri) { 377 Extension ex = ExtensionHelper.getExtension(c, uri); 378 if (ex == null) 379 return false; 380 if (!(ex.getValue() instanceof StringType)) 381 return false; 382 return !StringUtils.isBlank(((StringType) ex.getValue()).getValue()); 383 } 384 385 public static Boolean readBooleanExtension(Element c, String uri) { 386 Extension ex = ExtensionHelper.getExtension(c, uri); 387 if (ex == null) 388 return null; 389 if (!(ex.getValue() instanceof BooleanType)) 390 return null; 391 return ((BooleanType) ex.getValue()).getValue(); 392 } 393 394 public static boolean findBooleanExtension(Element c, String uri) { 395 Extension ex = ExtensionHelper.getExtension(c, uri); 396 if (ex == null) 397 return false; 398 if (!(ex.getValue() instanceof BooleanType)) 399 return false; 400 return true; 401 } 402 403 public static Boolean readBooleanExtension(DomainResource c, String uri) { 404 Extension ex = ExtensionHelper.getExtension(c, uri); 405 if (ex == null) 406 return null; 407 if (!(ex.getValue() instanceof BooleanType)) 408 return null; 409 return ((BooleanType) ex.getValue()).getValue(); 410 } 411 412 public static boolean readBoolExtension(DomainResource c, String uri) { 413 Extension ex = ExtensionHelper.getExtension(c, uri); 414 if (ex == null) 415 return false; 416 if (!(ex.getValue() instanceof BooleanType)) 417 return false; 418 return ((BooleanType) ex.getValue()).getValue(); 419 } 420 421 public static boolean findBooleanExtension(DomainResource c, String uri) { 422 Extension ex = ExtensionHelper.getExtension(c, uri); 423 if (ex == null) 424 return false; 425 if (!(ex.getValue() instanceof BooleanType)) 426 return false; 427 return true; 428 } 429 430 public static String getCSComment(ConceptDefinitionComponent c) { 431 return readStringExtension(c, EXT_CS_COMMENT); 432 } 433// 434// public static Boolean getDeprecated(Element c) { 435// return readBooleanExtension(c, EXT_DEPRECATED); 436// } 437 438 public static boolean hasCSComment(ConceptDefinitionComponent c) { 439 return findStringExtension(c, EXT_CS_COMMENT); 440 } 441 442// public static boolean hasDeprecated(Element c) { 443// return findBooleanExtension(c, EXT_DEPRECATED); 444// } 445 446 public static void addFlyOver(QuestionnaireItemComponent item, String text) { 447 if (!StringUtils.isBlank(text)) { 448 QuestionnaireItemComponent display = item.addItem(); 449 display.setType(QuestionnaireItemType.DISPLAY); 450 display.setText(text); 451 display.getExtension().add(Factory.newExtension(EXT_CONTROL, 452 Factory.newCodeableConcept("flyover", "http://hl7.org/fhir/questionnaire-item-control", "Fly-over"), true)); 453 } 454 } 455 456 public static void addMin(QuestionnaireItemComponent item, int min) { 457 item.getExtension().add(Factory.newExtension(EXT_MINOCCURS, Factory.newInteger(min), true)); 458 } 459 460 public static void addMax(QuestionnaireItemComponent item, int max) { 461 item.getExtension().add(Factory.newExtension(EXT_MAXOCCURS, Factory.newInteger(max), true)); 462 } 463 464 public static void addFhirType(QuestionnaireItemComponent group, String value) { 465 group.getExtension().add(Factory.newExtension(EXT_FHIRTYPE, Factory.newString_(value), true)); 466 } 467 468 public static void addControl(QuestionnaireItemComponent group, String value) { 469 group.getExtension().add(Factory.newExtension(EXT_CONTROL, 470 Factory.newCodeableConcept(value, "http://hl7.org/fhir/questionnaire-item-control", value), true)); 471 } 472 473 public static void addAllowedResource(QuestionnaireItemComponent group, String value) { 474 group.getExtension().add(Factory.newExtension(EXT_ALLOWEDRESOURCE, Factory.newCode(value), true)); 475 } 476 477 public static void addReferenceFilter(QuestionnaireItemComponent group, String value) { 478 group.getExtension().add(Factory.newExtension(EXT_REFERENCEFILTER, Factory.newString_(value), true)); 479 } 480 481 public static void addIdentifier(Element element, Identifier value) { 482 element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true)); 483 } 484 485 /** 486 * @param name the identity of the extension of interest 487 * @return The extension, if on this element, else null 488 */ 489 public static Extension getExtension(DomainResource resource, String name) { 490 if (name == null) 491 return null; 492 if (!resource.hasExtension()) 493 return null; 494 for (Extension e : resource.getExtension()) { 495 if (name.equals(e.getUrl())) 496 return e; 497 } 498 return null; 499 } 500 501 public static Extension getExtension(Element el, String name) { 502 if (name == null) 503 return null; 504 if (!el.hasExtension()) 505 return null; 506 for (Extension e : el.getExtension()) { 507 if (name.equals(e.getUrl())) 508 return e; 509 } 510 return null; 511 } 512 513 public static void setStringExtension(DomainResource resource, String uri, String value) { 514 if (Utilities.noString(value)) 515 return; 516 Extension ext = getExtension(resource, uri); 517 if (ext != null) 518 ext.setValue(new StringType(value)); 519 else 520 resource.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value))); 521 } 522 523 public static void setStringExtension(Element resource, String uri, String value) { 524 if (Utilities.noString(value)) 525 return; 526 Extension ext = getExtension(resource, uri); 527 if (ext != null) 528 ext.setValue(new StringType(value)); 529 else 530 resource.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value))); 531 } 532 533 public static void setCodeExtension(DomainResource resource, String uri, String value) { 534 if (Utilities.noString(value)) 535 return; 536 537 Extension ext = getExtension(resource, uri); 538 if (ext != null) 539 ext.setValue(new CodeType(value)); 540 else 541 resource.getExtension().add(new Extension(new UriType(uri)).setValue(new CodeType(value))); 542 } 543 544 public static void setCodeExtension(Element element, String uri, String value) { 545 if (Utilities.noString(value)) 546 return; 547 548 Extension ext = getExtension(element, uri); 549 if (ext != null) 550 ext.setValue(new CodeType(value)); 551 else 552 element.getExtension().add(new Extension(new UriType(uri)).setValue(new CodeType(value))); 553 } 554 555 556 public static void setCodeExtensionMod(DomainResource resource, String uri, String value) { 557 if (Utilities.noString(value)) 558 return; 559 560 Extension ext = getExtension(resource, uri); 561 if (ext != null) 562 ext.setValue(new CodeType(value)); 563 else 564 resource.getModifierExtension().add(new Extension(uri).setValue(new CodeType(value))); 565 } 566 567 public static void setCodeExtensionMod(BackboneElement resource, String uri, String value) { 568 if (Utilities.noString(value)) 569 return; 570 571 Extension ext = getExtension(resource, uri); 572 if (ext != null) 573 ext.setValue(new CodeType(value)); 574 else 575 resource.getModifierExtension().add(new Extension(uri).setValue(new CodeType(value))); 576 } 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(new UriType(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 Type 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( 801 ToolingExtensions.readStringExtension(issue, "http://hl7.org/fhir/StructureDefinition/rendering-xhtml")); 802 return vm; 803 } 804 805 private static IssueType mapType(org.hl7.fhir.r4.model.OperationOutcome.IssueType code) { 806 switch (code) { 807 case BUSINESSRULE: 808 return IssueType.BUSINESSRULE; 809 case CODEINVALID: 810 return IssueType.CODEINVALID; 811 case CONFLICT: 812 return IssueType.CONFLICT; 813 case DELETED: 814 return IssueType.DELETED; 815 case DUPLICATE: 816 return IssueType.DUPLICATE; 817 case EXCEPTION: 818 return IssueType.EXCEPTION; 819 case EXPIRED: 820 return IssueType.EXPIRED; 821 case EXTENSION: 822 return IssueType.EXTENSION; 823 case FORBIDDEN: 824 return IssueType.FORBIDDEN; 825 case INCOMPLETE: 826 return IssueType.INCOMPLETE; 827 case INFORMATIONAL: 828 return IssueType.INFORMATIONAL; 829 case INVALID: 830 return IssueType.INVALID; 831 case INVARIANT: 832 return IssueType.INVARIANT; 833 case LOCKERROR: 834 return IssueType.LOCKERROR; 835 case LOGIN: 836 return IssueType.LOGIN; 837 case MULTIPLEMATCHES: 838 return IssueType.MULTIPLEMATCHES; 839 case NOSTORE: 840 return IssueType.NOSTORE; 841 case NOTFOUND: 842 return IssueType.NOTFOUND; 843 case NOTSUPPORTED: 844 return IssueType.NOTSUPPORTED; 845 case NULL: 846 return IssueType.NULL; 847 case PROCESSING: 848 return IssueType.PROCESSING; 849 case REQUIRED: 850 return IssueType.REQUIRED; 851 case SECURITY: 852 return IssueType.SECURITY; 853 case STRUCTURE: 854 return IssueType.STRUCTURE; 855 case SUPPRESSED: 856 return IssueType.SUPPRESSED; 857 case THROTTLED: 858 return IssueType.THROTTLED; 859 case TIMEOUT: 860 return IssueType.TIMEOUT; 861 case TOOCOSTLY: 862 return IssueType.TOOCOSTLY; 863 case TOOLONG: 864 return IssueType.TOOLONG; 865 case TRANSIENT: 866 return IssueType.TRANSIENT; 867 case UNKNOWN: 868 return IssueType.UNKNOWN; 869 case VALUE: 870 return IssueType.VALUE; 871 default: 872 return null; 873 } 874 } 875 876 private static IssueSeverity mapSeverity(org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity severity) { 877 switch (severity) { 878 case ERROR: 879 return IssueSeverity.ERROR; 880 case FATAL: 881 return IssueSeverity.FATAL; 882 case INFORMATION: 883 return IssueSeverity.INFORMATION; 884 case WARNING: 885 return IssueSeverity.WARNING; 886 default: 887 return null; 888 } 889 } 890 891// public static boolean hasOID(ValueSet vs) { 892// return hasExtension(vs, EXT_OID); 893// } 894// 895// public static boolean hasOID(CodeSystem cs) { 896// return hasExtension(cs, EXT_OID); 897// } 898// 899 900}