001package org.hl7.fhir.r5.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.r5.model.Base; 073import org.hl7.fhir.r5.model.BooleanType; 074import org.hl7.fhir.r5.model.CanonicalResource; 075import org.hl7.fhir.r5.model.CanonicalType; 076import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; 077import org.hl7.fhir.r5.model.CodeType; 078import org.hl7.fhir.r5.model.CodeableConcept; 079import org.hl7.fhir.r5.model.Coding; 080import org.hl7.fhir.r5.model.DataType; 081import org.hl7.fhir.r5.model.DecimalType; 082import org.hl7.fhir.r5.model.DomainResource; 083import org.hl7.fhir.r5.model.Element; 084import org.hl7.fhir.r5.model.ElementDefinition; 085import org.hl7.fhir.r5.model.Extension; 086import org.hl7.fhir.r5.model.ExtensionHelper; 087import org.hl7.fhir.r5.model.Factory; 088import org.hl7.fhir.r5.model.Identifier; 089import org.hl7.fhir.r5.model.Integer64Type; 090import org.hl7.fhir.r5.model.IntegerType; 091import org.hl7.fhir.r5.model.MarkdownType; 092import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; 093import org.hl7.fhir.r5.model.PrimitiveType; 094import org.hl7.fhir.r5.model.Property; 095import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent; 096import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType; 097import org.hl7.fhir.r5.model.StringType; 098import org.hl7.fhir.r5.model.UriType; 099import org.hl7.fhir.r5.model.UrlType; 100import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent; 101import org.hl7.fhir.r5.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 public static final String EXT_EXPAND_RULES = "http://hl7.org/fhir/StructureDefinition/valueset-expand-rules"; 202 public static final String EXT_EXPAND_GROUP = "http://hl7.org/fhir/StructureDefinition/valueset-expand-group"; 203 public static final String EXT_BINDING_ADDITIONAL = "http://hl7.org/fhir/tools/StructureDefinition/additional-binding"; 204 205 // specific extension helpers 206 207 public static Extension makeIssueSource(Source source) { 208 Extension ex = new Extension(); 209 // todo: write this up and get it published with the pack (and handle the redirect?) 210 ex.setUrl(ToolingExtensions.EXT_ISSUE_SOURCE); 211 CodeType c = new CodeType(); 212 c.setValue(source.toString()); 213 ex.setValue(c); 214 return ex; 215 } 216 217 public static boolean hasExtension(DomainResource de, String url) { 218 return getExtension(de, url) != null; 219 } 220 221 public static boolean hasExtension(Element e, String url) { 222 return getExtension(e, url) != null; 223 } 224 225// public static void addStringExtension(DomainResource dr, String url, String content) { 226// if (!StringUtils.isBlank(content)) { 227// Extension ex = getExtension(dr, url); 228// if (ex != null) 229// ex.setValue(new StringType(content)); 230// else 231// dr.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 232// } 233// } 234 235 public static void addMarkdownExtension(DomainResource dr, String url, String content) { 236 if (!StringUtils.isBlank(content)) { 237 Extension ex = getExtension(dr, url); 238 if (ex != null) 239 ex.setValue(new StringType(content)); 240 else 241 dr.getExtension().add(Factory.newExtension(url, new MarkdownType(content), true)); 242 } 243 } 244 245 public static void addStringExtension(Element e, String url, String content) { 246 if (!StringUtils.isBlank(content)) { 247 Extension ex = getExtension(e, url); 248 if (ex != null) 249 ex.setValue(new StringType(content)); 250 else 251 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 252 } 253 } 254 255 public static void addCodeExtension(Element e, String url, String content) { 256 if (!StringUtils.isBlank(content)) { 257 Extension ex = getExtension(e, url); 258 if (ex != null) 259 ex.setValue(new CodeType(content)); 260 else 261 e.getExtension().add(Factory.newExtension(url, new CodeType(content), true)); 262 } 263 } 264 265 public static void addStringExtension(DomainResource e, String url, String content) { 266 if (!StringUtils.isBlank(content)) { 267 Extension ex = getExtension(e, url); 268 if (ex != null) 269 ex.setValue(new StringType(content)); 270 else 271 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 272 } 273 } 274 275 276 public static void addBooleanExtension(Element e, String url, boolean content) { 277 Extension ex = getExtension(e, url); 278 if (ex != null) 279 ex.setValue(new BooleanType(content)); 280 else 281 e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true)); 282 } 283 284 public static void addBooleanExtension(DomainResource e, String url, boolean content) { 285 Extension ex = getExtension(e, url); 286 if (ex != null) 287 ex.setValue(new BooleanType(content)); 288 else 289 e.getExtension().add(Factory.newExtension(url, new BooleanType(content), true)); 290 } 291 292 public static void addIntegerExtension(DomainResource dr, String url, int value) { 293 Extension ex = getExtension(dr, url); 294 if (ex != null) 295 ex.setValue(new IntegerType(value)); 296 else 297 dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true)); 298 } 299 300 public static void addCodeExtension(DomainResource dr, String url, String value) { 301 Extension ex = getExtension(dr, url); 302 if (ex != null) 303 ex.setValue(new CodeType(value)); 304 else 305 dr.getExtension().add(Factory.newExtension(url, new CodeType(value), true)); 306 } 307 308 public static void addVSComment(ConceptSetComponent nc, String comment) { 309 if (!StringUtils.isBlank(comment)) 310 nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true)); 311 } 312 public static void addVSComment(ConceptReferenceComponent nc, String comment) { 313 if (!StringUtils.isBlank(comment)) 314 nc.getExtension().add(Factory.newExtension(EXT_VS_COMMENT, Factory.newString_(comment), true)); 315 } 316 317 public static void addCSComment(ConceptDefinitionComponent nc, String comment) { 318 if (!StringUtils.isBlank(comment)) 319 nc.getExtension().add(Factory.newExtension(EXT_CS_COMMENT, Factory.newString_(comment), true)); 320 } 321 322// public static void markDeprecated(Element nc) { 323// setDeprecated(nc); 324// } 325// 326 327 public static void addDefinition(Element nc, String definition) { 328 if (!StringUtils.isBlank(definition)) 329 nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true)); 330 } 331 332 public static void addDisplayHint(Element def, String hint) { 333 if (!StringUtils.isBlank(hint)) 334 def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true)); 335 } 336 337 public static String getDisplayHint(Element def) { 338 return readStringExtension(def, EXT_DISPLAY_HINT); 339 } 340 341 public static String readStringExtension(Element c, String uri) { 342 Extension ex = ExtensionHelper.getExtension(c, uri); 343 if (ex == null) 344 return null; 345 if (ex.getValue() instanceof UriType) 346 return ((UriType) ex.getValue()).getValue(); 347 if (ex.getValue() instanceof CanonicalType) 348 return ((CanonicalType) ex.getValue()).getValue(); 349 if (ex.getValue() instanceof CodeType) 350 return ((CodeType) ex.getValue()).getValue(); 351 if (ex.getValue() instanceof IntegerType) 352 return ((IntegerType) ex.getValue()).asStringValue(); 353 if (ex.getValue() instanceof Integer64Type) 354 return ((Integer64Type) ex.getValue()).asStringValue(); 355 if (ex.getValue() instanceof DecimalType) 356 return ((DecimalType) ex.getValue()).asStringValue(); 357 if ((ex.getValue() instanceof MarkdownType)) 358 return ((MarkdownType) ex.getValue()).getValue(); 359 if ((ex.getValue() instanceof PrimitiveType)) 360 return ((PrimitiveType) ex.getValue()).primitiveValue(); 361 if (!(ex.getValue() instanceof StringType)) 362 return null; 363 return ((StringType) ex.getValue()).getValue(); 364 } 365 366 public static String readStringExtension(DomainResource c, String uri) { 367 Extension ex = getExtension(c, uri); 368 if (ex == null) 369 return null; 370 if ((ex.getValue() instanceof StringType)) 371 return ((StringType) ex.getValue()).getValue(); 372 if ((ex.getValue() instanceof UriType)) 373 return ((UriType) ex.getValue()).getValue(); 374 if (ex.getValue() instanceof CodeType) 375 return ((CodeType) ex.getValue()).getValue(); 376 if (ex.getValue() instanceof IntegerType) 377 return ((IntegerType) ex.getValue()).asStringValue(); 378 if (ex.getValue() instanceof Integer64Type) 379 return ((Integer64Type) ex.getValue()).asStringValue(); 380 if (ex.getValue() instanceof DecimalType) 381 return ((DecimalType) ex.getValue()).asStringValue(); 382 if ((ex.getValue() instanceof MarkdownType)) 383 return ((MarkdownType) ex.getValue()).getValue(); 384 return null; 385 } 386 387 @SuppressWarnings("unchecked") 388 public static PrimitiveType<DataType> readPrimitiveExtension(DomainResource c, String uri) { 389 Extension ex = getExtension(c, uri); 390 if (ex == null) 391 return null; 392 return (PrimitiveType<DataType>) ex.getValue(); 393 } 394 395 public static boolean findStringExtension(Element c, String uri) { 396 Extension ex = ExtensionHelper.getExtension(c, uri); 397 if (ex == null) 398 return false; 399 if (!(ex.getValue() instanceof StringType)) 400 return false; 401 return !StringUtils.isBlank(((StringType) ex.getValue()).getValue()); 402 } 403 404 public static Boolean readBooleanExtension(Element c, String uri) { 405 Extension ex = ExtensionHelper.getExtension(c, uri); 406 if (ex == null) 407 return null; 408 if (!(ex.getValue() instanceof BooleanType)) 409 return null; 410 return ((BooleanType) ex.getValue()).getValue(); 411 } 412 413 public static boolean findBooleanExtension(Element c, String uri) { 414 Extension ex = ExtensionHelper.getExtension(c, uri); 415 if (ex == null) 416 return false; 417 if (!(ex.getValue() instanceof BooleanType)) 418 return false; 419 return true; 420 } 421 422 public static Boolean readBooleanExtension(DomainResource c, String uri) { 423 Extension ex = ExtensionHelper.getExtension(c, uri); 424 if (ex == null) 425 return null; 426 if (!(ex.getValue() instanceof BooleanType)) 427 return null; 428 return ((BooleanType) ex.getValue()).getValue(); 429 } 430 431 public static boolean readBoolExtension(DomainResource c, String uri) { 432 Extension ex = ExtensionHelper.getExtension(c, uri); 433 if (ex == null) 434 return false; 435 if (!(ex.getValue() instanceof BooleanType)) 436 return false; 437 return ((BooleanType) ex.getValue()).getValue(); 438 } 439 440 public static boolean readBoolExtension(Element e, String uri) { 441 Extension ex = ExtensionHelper.getExtension(e, uri); 442 if (ex == null) 443 return false; 444 if (!(ex.getValue() instanceof BooleanType)) 445 return false; 446 return ((BooleanType) ex.getValue()).getValue(); 447 } 448 449 public static boolean findBooleanExtension(DomainResource c, String uri) { 450 Extension ex = ExtensionHelper.getExtension(c, uri); 451 if (ex == null) 452 return false; 453 if (!(ex.getValue() instanceof BooleanType)) 454 return false; 455 return true; 456 } 457 458 public static String getCSComment(ConceptDefinitionComponent c) { 459 return readStringExtension(c, EXT_CS_COMMENT); 460 } 461// 462// public static Boolean getDeprecated(Element c) { 463// return readBooleanExtension(c, EXT_DEPRECATED); 464// } 465 466 public static boolean hasCSComment(ConceptDefinitionComponent c) { 467 return findStringExtension(c, EXT_CS_COMMENT); 468 } 469 470// public static boolean hasDeprecated(Element c) { 471// return findBooleanExtension(c, EXT_DEPRECATED); 472// } 473 474 public static void addFlyOver(QuestionnaireItemComponent item, String text, String linkId){ 475 if (!StringUtils.isBlank(text)) { 476 QuestionnaireItemComponent display = item.addItem(); 477 display.setType(QuestionnaireItemType.DISPLAY); 478 display.setText(text); 479 display.setLinkId(linkId); 480 display.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept("flyover", "http://hl7.org/fhir/questionnaire-item-control", "Fly-over"), true)); 481 } 482 } 483 484 public static void addMin(QuestionnaireItemComponent item, int min) { 485 item.getExtension().add(Factory.newExtension(EXT_MINOCCURS, Factory.newInteger(min), true)); 486 } 487 488 public static void addMax(QuestionnaireItemComponent item, int max) { 489 item.getExtension().add(Factory.newExtension(EXT_MAXOCCURS, Factory.newInteger(max), true)); 490 } 491 492 public static void addFhirType(QuestionnaireItemComponent group, String value) { 493 group.getExtension().add(Factory.newExtension(EXT_FHIRTYPE, Factory.newString_(value), true)); 494 } 495 496 public static void addControl(QuestionnaireItemComponent group, String value) { 497 group.getExtension().add(Factory.newExtension(EXT_CONTROL, Factory.newCodeableConcept(value, "http://hl7.org/fhir/questionnaire-item-control", value), true)); 498 } 499 500 public static void addAllowedResource(QuestionnaireItemComponent group, String value) { 501 group.getExtension().add(Factory.newExtension(EXT_ALLOWEDRESOURCE, Factory.newCode(value), true)); 502 } 503 504 public static void addReferenceFilter(QuestionnaireItemComponent group, String value) { 505 group.getExtension().add(Factory.newExtension(EXT_REFERENCEFILTER, Factory.newString_(value), true)); 506 } 507 508 public static void addIdentifier(Element element, Identifier value) { 509 element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true)); 510 } 511 512 /** 513 * @param name the identity of the extension of interest 514 * @return The extension, if on this element, else null 515 */ 516 public static Extension getExtension(DomainResource resource, String name) { 517 if (resource == null || name == null) 518 return null; 519 if (!resource.hasExtension()) 520 return null; 521 for (Extension e : resource.getExtension()) { 522 if (name.equals(e.getUrl())) 523 return e; 524 } 525 return null; 526 } 527 528 public static Extension getExtension(Element el, String name) { 529 if (name == null) 530 return null; 531 if (!el.hasExtension()) 532 return null; 533 for (Extension e : el.getExtension()) { 534 if (name.equals(e.getUrl())) 535 return e; 536 } 537 return null; 538 } 539 540 public static void setStringExtension(DomainResource resource, String uri, String value) { 541 if (Utilities.noString(value)) 542 return; 543 Extension ext = getExtension(resource, uri); 544 if (ext != null) 545 ext.setValue(new StringType(value)); 546 else 547 resource.getExtension().add(new Extension(uri).setValue(new StringType(value))); 548 } 549 550 public static void setStringExtension(Element resource, String uri, String value) { 551 if (Utilities.noString(value)) 552 return; 553 Extension ext = getExtension(resource, uri); 554 if (ext != null) 555 ext.setValue(new StringType(value)); 556 else 557 resource.getExtension().add(new Extension(uri).setValue(new StringType(value))); 558 } 559 560 public static void setCodeExtension(DomainResource resource, String uri, String value) { 561 if (Utilities.noString(value)) 562 return; 563 564 Extension ext = getExtension(resource, uri); 565 if (ext != null) 566 ext.setValue(new CodeType(value)); 567 else 568 resource.getExtension().add(new Extension(uri).setValue(new CodeType(value))); 569 } 570 571 public static void setCodeExtension(Element element, String uri, String value) { 572 if (Utilities.noString(value)) 573 return; 574 575 Extension ext = getExtension(element, uri); 576 if (ext != null) 577 ext.setValue(new CodeType(value)); 578 else 579 element.getExtension().add(new Extension(uri).setValue(new CodeType(value))); 580 } 581 582 public static void setIntegerExtension(DomainResource resource, String uri, int value) { 583 Extension ext = getExtension(resource, uri); 584 if (ext != null) 585 ext.setValue(new IntegerType(value)); 586 else 587 resource.getExtension().add(new Extension(uri).setValue(new IntegerType(value))); 588 } 589 590// public static String getOID(CodeSystem define) { 591// return readStringExtension(define, EXT_OID); 592// } 593// 594// public static String getOID(ValueSet vs) { 595// return readStringExtension(vs, EXT_OID); 596// } 597// 598// public static void setOID(CodeSystem define, String oid) throws FHIRFormatError, URISyntaxException { 599// if (!oid.startsWith("urn:oid:")) 600// throw new FHIRFormatError("Error in OID format"); 601// if (oid.startsWith("urn:oid:urn:oid:")) 602// throw new FHIRFormatError("Error in OID format"); 603// if (!hasExtension(define, EXT_OID)) 604// define.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false)); 605// else if (!oid.equals(readStringExtension(define, EXT_OID))) 606// throw new Error("Attempt to assign multiple OIDs to a code system"); 607// } 608// public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException { 609// if (!oid.startsWith("urn:oid:")) 610// throw new FHIRFormatError("Error in OID format"); 611// if (oid.startsWith("urn:oid:urn:oid:")) 612// throw new FHIRFormatError("Error in OID format"); 613// if (!hasExtension(vs, EXT_OID)) 614// vs.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false)); 615// else if (!oid.equals(readStringExtension(vs, EXT_OID))) 616// throw new Error("Attempt to assign multiple OIDs to value set "+vs.getName()+" ("+vs.getUrl()+"). Has "+readStringExtension(vs, EXT_OID)+", trying to add "+oid); 617// } 618 619 public static boolean hasLanguageTranslation(Element element, String lang) { 620 for (Extension e : element.getExtension()) { 621 if (e.getUrl().equals(EXT_TRANSLATION)) { 622 Extension e1 = ExtensionHelper.getExtension(e, "lang"); 623 624 if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) 625 return true; 626 } 627 } 628 return false; 629 } 630 631 public static String getLanguageTranslation(Element element, String lang) { 632 for (Extension e : element.getExtension()) { 633 if (e.getUrl().equals(EXT_TRANSLATION)) { 634 Extension e1 = ExtensionHelper.getExtension(e, "lang"); 635 636 if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) { 637 e1 = ExtensionHelper.getExtension(e, "content"); 638 return ((StringType) e.getValue()).getValue(); 639 } 640 } 641 } 642 return null; 643 } 644 645 public static void addLanguageTranslation(Element element, String lang, String value) { 646 if (Utilities.noString(lang) || Utilities.noString(value)) 647 return; 648 649 Extension extension = new Extension().setUrl(EXT_TRANSLATION); 650 extension.addExtension().setUrl("lang").setValue(new CodeType(lang)); 651 extension.addExtension().setUrl("content").setValue(new StringType(value)); 652 element.getExtension().add(extension); 653 } 654 655 public static DataType getAllowedUnits(ElementDefinition eld) { 656 for (Extension e : eld.getExtension()) 657 if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) 658 return e.getValue(); 659 return null; 660 } 661 662 public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) { 663 for (Extension e : eld.getExtension()) 664 if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) { 665 e.setValue(cc); 666 return; 667 } 668 eld.getExtension().add(new Extension().setUrl(EXT_ALLOWABLE_UNITS).setValue(cc)); 669 } 670 671 public static List<Extension> getExtensions(Element element, String url) { 672 List<Extension> results = new ArrayList<Extension>(); 673 for (Extension ex : element.getExtension()) 674 if (ex.getUrl().equals(url)) 675 results.add(ex); 676 return results; 677 } 678 679 public static List<Extension> getExtensions(DomainResource resource, String url) { 680 List<Extension> results = new ArrayList<Extension>(); 681 for (Extension ex : resource.getExtension()) 682 if (ex.getUrl().equals(url)) 683 results.add(ex); 684 return results; 685 } 686 687// public static void addDEReference(DataElement de, String value) { 688// for (Extension e : de.getExtension()) 689// if (e.getUrl().equals(EXT_CIMI_REFERENCE)) { 690// e.setValue(new UriType(value)); 691// return; 692// } 693// de.getExtension().add(new Extension().setUrl(EXT_CIMI_REFERENCE).setValue(new UriType(value))); 694// } 695 696// public static void setDeprecated(Element nc) { 697// for (Extension e : nc.getExtension()) 698// if (e.getUrl().equals(EXT_DEPRECATED)) { 699// e.setValue(new BooleanType(true)); 700// return; 701// } 702// nc.getExtension().add(new Extension().setUrl(EXT_DEPRECATED).setValue(new BooleanType(true))); 703// } 704 705 public static void setExtension(Element focus, String url, Coding c) { 706 for (Extension e : focus.getExtension()) 707 if (e.getUrl().equals(url)) { 708 e.setValue(c); 709 return; 710 } 711 focus.getExtension().add(new Extension().setUrl(url).setValue(c)); 712 } 713 714 public static void removeExtension(DomainResource focus, String url) { 715 Iterator<Extension> i = focus.getExtension().iterator(); 716 while (i.hasNext()) { 717 Extension e = i.next(); // must be called before you can call i.remove() 718 if (e.getUrl().equals(url)) { 719 i.remove(); 720 } 721 } 722 } 723 724 public static void removeExtension(Element focus, String url) { 725 Iterator<Extension> i = focus.getExtension().iterator(); 726 while (i.hasNext()) { 727 Extension e = i.next(); // must be called before you can call i.remove() 728 if (e.getUrl().equals(url)) { 729 i.remove(); 730 } 731 } 732 } 733 734 public static int readIntegerExtension(DomainResource dr, String uri, int defaultValue) { 735 Extension ex = ExtensionHelper.getExtension(dr, uri); 736 if (ex == null) 737 return defaultValue; 738 if (ex.getValue() instanceof IntegerType) 739 return ((IntegerType) ex.getValue()).getValue(); 740 throw new Error("Unable to read extension "+uri+" as an integer"); 741 } 742 743 public static int readIntegerExtension(Element e, String uri, int defaultValue) { 744 Extension ex = ExtensionHelper.getExtension(e, uri); 745 if (ex == null) 746 return defaultValue; 747 if (ex.getValue() instanceof IntegerType) 748 return ((IntegerType) ex.getValue()).getValue(); 749 throw new Error("Unable to read extension "+uri+" as an integer"); 750 } 751 752 public static Map<String, String> getLanguageTranslations(Element e) { 753 Map<String, String> res = new HashMap<String, String>(); 754 for (Extension ext : e.getExtension()) { 755 if (ext.getUrl().equals(EXT_TRANSLATION)) { 756 String lang = readStringExtension(ext, "lang"); 757 String value = readStringExtension(ext, "content"); 758 res.put(lang, value); 759 } 760 } 761 return res; 762 } 763 764 public static StandardsStatus getStandardsStatus(DomainResource dr) throws FHIRException { 765 return StandardsStatus.fromCode(ToolingExtensions.readStringExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS)); 766 } 767 768 public static void setStandardsStatus(DomainResource dr, StandardsStatus status, String normativeVersion) { 769 if (status == null) 770 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS); 771 else 772 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS, status.toCode()); 773 if (normativeVersion == null) 774 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION); 775 else 776 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION, normativeVersion); 777 } 778 779 public static void setStandardsStatus(Element dr, StandardsStatus status, String normativeVersion) { 780 if (status == null) 781 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS); 782 else 783 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_STANDARDS_STATUS, status.toCode()); 784 if (normativeVersion == null) 785 ToolingExtensions.removeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION); 786 else 787 ToolingExtensions.setCodeExtension(dr, ToolingExtensions.EXT_NORMATIVE_VERSION, normativeVersion); 788 } 789 790 public static ValidationMessage readValidationMessage(OperationOutcomeIssueComponent issue, Source source) { 791 ValidationMessage vm = new ValidationMessage(); 792 vm.setSource(source); 793 vm.setLevel(mapSeverity(issue.getSeverity())); 794 vm.setType(mapType(issue.getCode())); 795 if (issue.hasExtension(ToolingExtensions.EXT_ISSUE_LINE)) 796 vm.setLine(ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_LINE, 0)); 797 if (issue.hasExtension(ToolingExtensions.EXT_ISSUE_COL)) 798 vm.setCol(ToolingExtensions.readIntegerExtension(issue, ToolingExtensions.EXT_ISSUE_COL, 0)); 799 if (issue.hasExpression()) 800 vm.setLocation(issue.getExpression().get(0).asStringValue()); 801 vm.setMessage(issue.getDetails().getText()); 802 if (issue.hasExtension("http://hl7.org/fhir/StructureDefinition/rendering-xhtml")) 803 vm.setHtml(ToolingExtensions.readStringExtension(issue, "http://hl7.org/fhir/StructureDefinition/rendering-xhtml")); 804 return vm; 805 } 806 807 private static IssueType mapType(org.hl7.fhir.r5.model.OperationOutcome.IssueType code) { 808 switch (code) { 809 case BUSINESSRULE: return IssueType.BUSINESSRULE; 810 case CODEINVALID: return IssueType.CODEINVALID; 811 case CONFLICT: return IssueType.CONFLICT; 812 case DELETED: return IssueType.DELETED; 813 case DUPLICATE: return IssueType.DUPLICATE; 814 case EXCEPTION: return IssueType.EXCEPTION; 815 case EXPIRED: return IssueType.EXPIRED; 816 case EXTENSION: return IssueType.EXTENSION; 817 case FORBIDDEN: return IssueType.FORBIDDEN; 818 case INCOMPLETE: return IssueType.INCOMPLETE; 819 case INFORMATIONAL: return IssueType.INFORMATIONAL; 820 case INVALID: return IssueType.INVALID; 821 case INVARIANT: return IssueType.INVARIANT; 822 case LOCKERROR: return IssueType.LOCKERROR; 823 case LOGIN: return IssueType.LOGIN; 824 case MULTIPLEMATCHES: return IssueType.MULTIPLEMATCHES; 825 case NOSTORE: return IssueType.NOSTORE; 826 case NOTFOUND: return IssueType.NOTFOUND; 827 case NOTSUPPORTED: return IssueType.NOTSUPPORTED; 828 case NULL: return IssueType.NULL; 829 case PROCESSING: return IssueType.PROCESSING; 830 case REQUIRED: return IssueType.REQUIRED; 831 case SECURITY: return IssueType.SECURITY; 832 case STRUCTURE: return IssueType.STRUCTURE; 833 case SUPPRESSED: return IssueType.SUPPRESSED; 834 case THROTTLED: return IssueType.THROTTLED; 835 case TIMEOUT: return IssueType.TIMEOUT; 836 case TOOCOSTLY: return IssueType.TOOCOSTLY; 837 case TOOLONG: return IssueType.TOOLONG; 838 case TRANSIENT: return IssueType.TRANSIENT; 839 case UNKNOWN: return IssueType.UNKNOWN; 840 case VALUE: return IssueType.VALUE; 841 default: return null; 842 } 843 } 844 845 private static IssueSeverity mapSeverity(org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity severity) { 846 switch (severity) { 847 case ERROR: return IssueSeverity.ERROR; 848 case FATAL: return IssueSeverity.FATAL; 849 case INFORMATION: return IssueSeverity.INFORMATION; 850 case WARNING: return IssueSeverity.WARNING; 851 default: return null; 852 } 853 } 854 855 public static String getPresentation(PrimitiveType<?> type) { 856 if (type.hasExtension(EXT_RENDERED_VALUE)) 857 return readStringExtension(type, EXT_RENDERED_VALUE); 858 return type.primitiveValue(); 859 } 860 861 public static String getPresentation(Element holder, PrimitiveType<?> type) { 862 if (holder.hasExtension(EXT_RENDERED_VALUE)) 863 return readStringExtension(holder, EXT_RENDERED_VALUE); 864 if (type.hasExtension(EXT_RENDERED_VALUE)) 865 return readStringExtension(type, EXT_RENDERED_VALUE); 866 return type.primitiveValue(); 867 } 868 869// public static boolean hasOID(ValueSet vs) { 870// return hasExtension(vs, EXT_OID); 871// } 872// 873// public static boolean hasOID(CodeSystem cs) { 874// return hasExtension(cs, EXT_OID); 875// } 876// 877 public static void addUrlExtension(Element e, String url, String content) { 878 if (!StringUtils.isBlank(content)) { 879 Extension ex = getExtension(e, url); 880 if (ex != null) 881 ex.setValue(new UrlType(content)); 882 else 883 e.getExtension().add(Factory.newExtension(url, new UrlType(content), true)); 884 } 885 } 886 887 public static void addUrlExtension(DomainResource dr, String url, String value) { 888 Extension ex = getExtension(dr, url); 889 if (ex != null) 890 ex.setValue(new UrlType(value)); 891 else 892 dr.getExtension().add(Factory.newExtension(url, new UrlType(value), true)); 893 } 894 895 public static void addUriExtension(Element e, String url, String content) { 896 if (!StringUtils.isBlank(content)) { 897 Extension ex = getExtension(e, url); 898 if (ex != null) 899 ex.setValue(new UriType(content)); 900 else 901 e.getExtension().add(Factory.newExtension(url, new UriType(content), true)); 902 } 903 } 904 905 public static void addUriExtension(DomainResource dr, String url, String value) { 906 Extension ex = getExtension(dr, url); 907 if (ex != null) 908 ex.setValue(new UriType(value)); 909 else 910 dr.getExtension().add(Factory.newExtension(url, new UriType(value), true)); 911 } 912 913 public static boolean usesExtension(String url, Base base) { 914 if ("Extension".equals(base.fhirType())) { 915 Property p = base.getNamedProperty("url"); 916 for (Base b : p.getValues()) { 917 if (url.equals(b.primitiveValue())) { 918 return true; 919 } 920 } 921 } 922 923 for (Property p : base.children() ) { 924 for (Base v : p.getValues()) { 925 if (usesExtension(url, v)) { 926 return true; 927 } 928 } 929 } 930 return false; 931 } 932 933 934}