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