001package org.hl7.fhir.dstu2.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 034import java.net.URISyntaxException; 035 036/* 037Copyright (c) 2011+, HL7, Inc 038All rights reserved. 039 040Redistribution and use in source and binary forms, with or without modification, 041are permitted provided that the following conditions are met: 042 043 * Redistributions of source code must retain the above copyright notice, this 044 list of conditions and the following disclaimer. 045 * Redistributions in binary form must reproduce the above copyright notice, 046 this list of conditions and the following disclaimer in the documentation 047 and/or other materials provided with the distribution. 048 * Neither the name of HL7 nor the names of its contributors may be used to 049 endorse or promote products derived from this software without specific 050 prior written permission. 051 052THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 053ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 054WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 055IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 056INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 057NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 058PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 059WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 060ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 061POSSIBILITY OF SUCH DAMAGE. 062 063 */ 064 065import java.util.ArrayList; 066import java.util.Iterator; 067import java.util.List; 068 069import org.hl7.fhir.dstu2.model.BooleanType; 070import org.hl7.fhir.dstu2.model.CodeType; 071import org.hl7.fhir.dstu2.model.CodeableConcept; 072import org.hl7.fhir.dstu2.model.Coding; 073import org.hl7.fhir.dstu2.model.DataElement; 074import org.hl7.fhir.dstu2.model.DomainResource; 075import org.hl7.fhir.dstu2.model.Element; 076import org.hl7.fhir.dstu2.model.ElementDefinition; 077import org.hl7.fhir.dstu2.model.Extension; 078import org.hl7.fhir.dstu2.model.ExtensionHelper; 079import org.hl7.fhir.dstu2.model.Factory; 080import org.hl7.fhir.dstu2.model.Identifier; 081import org.hl7.fhir.dstu2.model.IntegerType; 082import org.hl7.fhir.dstu2.model.MarkdownType; 083import org.hl7.fhir.dstu2.model.PrimitiveType; 084import org.hl7.fhir.dstu2.model.Questionnaire.GroupComponent; 085import org.hl7.fhir.dstu2.model.Questionnaire.QuestionComponent; 086import org.hl7.fhir.dstu2.model.Reference; 087import org.hl7.fhir.dstu2.model.StringType; 088import org.hl7.fhir.dstu2.model.Type; 089import org.hl7.fhir.dstu2.model.UriType; 090import org.hl7.fhir.dstu2.model.ValueSet; 091import org.hl7.fhir.dstu2.model.ValueSet.ConceptDefinitionComponent; 092import org.hl7.fhir.dstu2.model.ValueSet.ValueSetCodeSystemComponent; 093import org.hl7.fhir.exceptions.FHIRFormatError; 094import org.hl7.fhir.utilities.Utilities; 095import org.hl7.fhir.utilities.validation.ValidationMessage.Source; 096 097 098public class ToolingExtensions { 099 100 // validated 101 public static final String EXT_SUBSUMES = "http://hl7.org/fhir/StructureDefinition/valueset-subsumes"; 102 private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid"; 103 public static final String EXT_DEPRECATED = "http://hl7.org/fhir/StructureDefinition/valueset-deprecated"; 104 public static final String EXT_DEFINITION = "http://hl7.org/fhir/StructureDefinition/valueset-definition"; 105 public static final String EXT_COMMENT = "http://hl7.org/fhir/StructureDefinition/valueset-comments"; 106 private static final String EXT_IDENTIFIER = "http://hl7.org/fhir/StructureDefinition/identifier"; 107 private static final String EXT_TRANSLATION = "http://hl7.org/fhir/StructureDefinition/translation"; 108 public static final String EXT_ISSUE_SOURCE = "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-source"; 109 public static final String EXT_DISPLAY_HINT = "http://hl7.org/fhir/StructureDefinition/structuredefinition-display-hint"; 110 public static final String EXT_REPLACED_BY = "http://hl7.org/fhir/StructureDefinition/valueset-replacedby"; 111 public static final String EXT_JSON_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-json-type"; 112 public static final String EXT_XML_TYPE = "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-type"; 113 public static final String EXT_REGEX = "http://hl7.org/fhir/StructureDefinition/structuredefinition-regex"; 114 public static final String EXT_EXPRESSION = "http://hl7.org/fhir/StructureDefinition/structuredefinition-expression"; 115 public static final String EXT_SEARCH_EXPRESSION = "http://hl7.org/fhir/StructureDefinition/searchparameter-expression"; 116 117 // unregistered? 118 119 public static final String EXT_FLYOVER = "http://hl7.org/fhir/Profile/questionnaire-extensions#flyover"; 120 private static final String EXT_QTYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type"; 121 private static final String EXT_QREF = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference"; 122 private static final String EXTENSION_FILTER_ONLY = "http://www.healthintersections.com.au/fhir/Profile/metadata#expandNeedsFilter"; 123 private static final String EXT_TYPE = "http://www.healthintersections.com.au/fhir/Profile/metadata#type"; 124 private static final String EXT_REFERENCE = "http://www.healthintersections.com.au/fhir/Profile/metadata#reference"; 125 private static final String EXT_ALLOWABLE_UNITS = "http://hl7.org/fhir/StructureDefinition/elementdefinition-allowedUnits"; 126 public static final String EXT_CIMI_REFERENCE = "http://hl7.org/fhir/StructureDefinition/cimi-reference"; 127 public static final String EXT_UNCLOSED = "http://hl7.org/fhir/StructureDefinition/valueset-unclosed"; 128 public static final String EXT_FMM_LEVEL = "http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm"; 129 130 131 // specific extension helpers 132 133 public static Extension makeIssueSource(Source source) { 134 Extension ex = new Extension(); 135 // todo: write this up and get it published with the pack (and handle the redirect?) 136 ex.setUrl(ToolingExtensions.EXT_ISSUE_SOURCE); 137 CodeType c = new CodeType(); 138 c.setValue(source.toString()); 139 ex.setValue(c); 140 return ex; 141 } 142 143 public static boolean hasExtension(DomainResource de, String url) { 144 return getExtension(de, url) != null; 145 } 146 147 public static boolean hasExtension(Element e, String url) { 148 return getExtension(e, url) != null; 149 } 150 151 public static void addStringExtension(DomainResource dr, String url, String content) { 152 if (!Utilities.noString(content)) { 153 Extension ex = getExtension(dr, url); 154 if (ex != null) 155 ex.setValue(new StringType(content)); 156 else 157 dr.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 158 } 159 } 160 161 public static void addStringExtension(Element e, String url, String content) { 162 if (!Utilities.noString(content)) { 163 Extension ex = getExtension(e, url); 164 if (ex != null) 165 ex.setValue(new StringType(content)); 166 else 167 e.getExtension().add(Factory.newExtension(url, new StringType(content), true)); 168 } 169 } 170 171 public static void addIntegerExtension(DomainResource dr, String url, int value) { 172 Extension ex = getExtension(dr, url); 173 if (ex != null) 174 ex.setValue(new IntegerType(value)); 175 else 176 dr.getExtension().add(Factory.newExtension(url, new IntegerType(value), true)); 177 } 178 179 public static void addComment(Element nc, String comment) { 180 if (!Utilities.noString(comment)) 181 nc.getExtension().add(Factory.newExtension(EXT_COMMENT, Factory.newString_(comment), true)); 182 } 183 184 public static void markDeprecated(Element nc) { 185 setDeprecated(nc); 186 } 187 188 public static void addSubsumes(ConceptDefinitionComponent nc, String code) { 189 nc.getModifierExtension().add(Factory.newExtension(EXT_SUBSUMES, Factory.newCode(code), true)); 190 } 191 192 public static void addDefinition(Element nc, String definition) { 193 if (!Utilities.noString(definition)) 194 nc.getExtension().add(Factory.newExtension(EXT_DEFINITION, Factory.newString_(definition), true)); 195 } 196 197 public static void addDisplayHint(Element def, String hint) { 198 if (!Utilities.noString(hint)) 199 def.getExtension().add(Factory.newExtension(EXT_DISPLAY_HINT, Factory.newString_(hint), true)); 200 } 201 202 public static String getDisplayHint(Element def) { 203 return readStringExtension(def, EXT_DISPLAY_HINT); 204 } 205 206 public static String readStringExtension(Element c, String uri) { 207 Extension ex = ExtensionHelper.getExtension(c, uri); 208 if (ex == null) 209 return null; 210 if (ex.getValue() instanceof UriType) 211 return ((UriType) ex.getValue()).getValue(); 212 if (!(ex.getValue() instanceof StringType)) 213 return null; 214 return ((StringType) ex.getValue()).getValue(); 215 } 216 217 public static String readStringExtension(DomainResource c, String uri) { 218 Extension ex = getExtension(c, uri); 219 if (ex == null) 220 return null; 221 if ((ex.getValue() instanceof StringType)) 222 return ((StringType) ex.getValue()).getValue(); 223 if ((ex.getValue() instanceof UriType)) 224 return ((UriType) ex.getValue()).getValue(); 225 if ((ex.getValue() instanceof MarkdownType)) 226 return ((MarkdownType) ex.getValue()).getValue(); 227 return null; 228 } 229 230 @SuppressWarnings("unchecked") 231 public static PrimitiveType<Type> readPrimitiveExtension(DomainResource c, String uri) { 232 Extension ex = getExtension(c, uri); 233 if (ex == null) 234 return null; 235 return (PrimitiveType<Type>) ex.getValue(); 236 } 237 238 public static boolean findStringExtension(Element c, String uri) { 239 Extension ex = ExtensionHelper.getExtension(c, uri); 240 if (ex == null) 241 return false; 242 if (!(ex.getValue() instanceof StringType)) 243 return false; 244 return !Utilities.noString(((StringType) ex.getValue()).getValue()); 245 } 246 247 public static Boolean readBooleanExtension(Element c, String uri) { 248 Extension ex = ExtensionHelper.getExtension(c, uri); 249 if (ex == null) 250 return null; 251 if (!(ex.getValue() instanceof BooleanType)) 252 return null; 253 return ((BooleanType) ex.getValue()).getValue(); 254 } 255 256 public static boolean findBooleanExtension(Element c, String uri) { 257 Extension ex = ExtensionHelper.getExtension(c, uri); 258 if (ex == null) 259 return false; 260 if (!(ex.getValue() instanceof BooleanType)) 261 return false; 262 return true; 263 } 264 265 public static String getComment(ConceptDefinitionComponent c) { 266 return readStringExtension(c, EXT_COMMENT); 267 } 268 269 public static Boolean getDeprecated(Element c) { 270 return readBooleanExtension(c, EXT_DEPRECATED); 271 } 272 273 public static boolean hasComment(ConceptDefinitionComponent c) { 274 return findStringExtension(c, EXT_COMMENT); 275 } 276 277 public static boolean hasDeprecated(Element c) { 278 return findBooleanExtension(c, EXT_DEPRECATED); 279 } 280 281 public static List<CodeType> getSubsumes(ConceptDefinitionComponent c) { 282 List<CodeType> res = new ArrayList<CodeType>(); 283 284 for (Extension e : c.getExtension()) { 285 if (EXT_SUBSUMES.equals(e.getUrl())) 286 res.add((CodeType) e.getValue()); 287 } 288 return res; 289 } 290 291 public static void addFlyOver(GroupComponent group, String text) { 292 if (!Utilities.noString(text)) 293 group.getExtension().add(Factory.newExtension(EXT_FLYOVER, Factory.newString_(text), true)); 294 295 } 296 297 public static void setQuestionType(GroupComponent group, String text) { 298 if (!Utilities.noString(text)) 299 group.getExtension().add(Factory.newExtension(EXT_QTYPE, Factory.newString_(text), true)); 300 } 301 302 public static void setQuestionReference(GroupComponent group, String text) { 303 if (!Utilities.noString(text)) 304 group.getExtension().add(Factory.newExtension(EXT_QREF, Factory.newString_(text), true)); 305 } 306 307 public static void addFlyOver(Element element, String text) { 308 element.getExtension().add(Factory.newExtension(EXT_FLYOVER, Factory.newString_(text), true)); 309 } 310 311 public static void addFilterOnly(Reference element, boolean value) { 312 element.getExtension().add(Factory.newExtension(EXTENSION_FILTER_ONLY, Factory.newBoolean(value), true)); 313 } 314 315 public static void addType(GroupComponent group, String value) { 316 group.getExtension().add(Factory.newExtension(EXT_TYPE, Factory.newString_(value), true)); 317 } 318 319 public static void addReference(QuestionComponent group, String value) { 320 group.getExtension().add(Factory.newExtension(EXT_REFERENCE, Factory.newString_(value), true)); 321 } 322 323 public static void addIdentifier(Element element, Identifier value) { 324 element.getExtension().add(Factory.newExtension(EXT_IDENTIFIER, value, true)); 325 } 326 327 /** 328 * @param name the identity of the extension of interest 329 * @return The extension, if on this element, else null 330 */ 331 public static Extension getExtension(DomainResource resource, String name) { 332 if (name == null) 333 return null; 334 if (!resource.hasExtension()) 335 return null; 336 for (Extension e : resource.getExtension()) { 337 if (name.equals(e.getUrl())) 338 return e; 339 } 340 return null; 341 } 342 343 public static Extension getExtension(Element el, String name) { 344 if (name == null) 345 return null; 346 if (!el.hasExtension()) 347 return null; 348 for (Extension e : el.getExtension()) { 349 if (name.equals(e.getUrl())) 350 return e; 351 } 352 return null; 353 } 354 355 public static void setStringExtension(DomainResource resource, String uri, String value) { 356 Extension ext = getExtension(resource, uri); 357 if (ext != null) 358 ext.setValue(new StringType(value)); 359 else 360 resource.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value))); 361 } 362 363 public static String getOID(ValueSetCodeSystemComponent define) { 364 return readStringExtension(define, EXT_OID); 365 } 366 367 public static String getOID(ValueSet vs) { 368 return readStringExtension(vs, EXT_OID); 369 } 370 371 public static void setOID(ValueSetCodeSystemComponent define, String oid) throws FHIRFormatError, URISyntaxException { 372 if (!oid.startsWith("urn:oid:")) 373 throw new FHIRFormatError("Error in OID format"); 374 if (oid.startsWith("urn:oid:urn:oid:")) 375 throw new FHIRFormatError("Error in OID format"); 376 define.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false)); 377 } 378 public static void setOID(ValueSet vs, String oid) throws FHIRFormatError, URISyntaxException { 379 if (!oid.startsWith("urn:oid:")) 380 throw new FHIRFormatError("Error in OID format"); 381 if (oid.startsWith("urn:oid:urn:oid:")) 382 throw new FHIRFormatError("Error in OID format"); 383 vs.getExtension().add(Factory.newExtension(EXT_OID, Factory.newUri(oid), false)); 384 } 385 386 public static boolean hasLanguageTranslation(Element element, String lang) { 387 for (Extension e : element.getExtension()) { 388 if (e.getUrl().equals(EXT_TRANSLATION)) { 389 Extension e1 = ExtensionHelper.getExtension(e, "lang"); 390 391 if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) 392 return true; 393 } 394 } 395 return false; 396 } 397 398 public static String getLanguageTranslation(Element element, String lang) { 399 for (Extension e : element.getExtension()) { 400 if (e.getUrl().equals(EXT_TRANSLATION)) { 401 Extension e1 = ExtensionHelper.getExtension(e, "lang"); 402 403 if (e1 != null && e1.getValue() instanceof CodeType && ((CodeType) e.getValue()).getValue().equals(lang)) { 404 e1 = ExtensionHelper.getExtension(e, "content"); 405 return ((StringType) e.getValue()).getValue(); 406 } 407 } 408 } 409 return null; 410 } 411 412 public static void addLanguageTranslation(Element element, String lang, String value) { 413 Extension extension = new Extension().setUrl(EXT_TRANSLATION); 414 extension.addExtension().setUrl("lang").setValue(new StringType(lang)); 415 extension.addExtension().setUrl("content").setValue(new StringType(value)); 416 element.getExtension().add(extension); 417 } 418 419 public static Type getAllowedUnits(ElementDefinition eld) { 420 for (Extension e : eld.getExtension()) 421 if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) 422 return e.getValue(); 423 return null; 424 } 425 426 public static void setAllowableUnits(ElementDefinition eld, CodeableConcept cc) { 427 for (Extension e : eld.getExtension()) 428 if (e.getUrl().equals(EXT_ALLOWABLE_UNITS)) { 429 e.setValue(cc); 430 return; 431 } 432 eld.getExtension().add(new Extension().setUrl(EXT_ALLOWABLE_UNITS).setValue(cc)); 433 } 434 435 public static List<Extension> getExtensions(Element element, String url) { 436 List<Extension> results = new ArrayList<Extension>(); 437 for (Extension ex : element.getExtension()) 438 if (ex.getUrl().equals(url)) 439 results.add(ex); 440 return results; 441 } 442 443 public static List<Extension> getExtensions(DomainResource resource, String url) { 444 List<Extension> results = new ArrayList<Extension>(); 445 for (Extension ex : resource.getExtension()) 446 if (ex.getUrl().equals(url)) 447 results.add(ex); 448 return results; 449 } 450 451 public static void addDEReference(DataElement de, String value) { 452 for (Extension e : de.getExtension()) 453 if (e.getUrl().equals(EXT_CIMI_REFERENCE)) { 454 e.setValue(new UriType(value)); 455 return; 456 } 457 de.getExtension().add(new Extension().setUrl(EXT_CIMI_REFERENCE).setValue(new UriType(value))); 458 } 459 460 public static void setDeprecated(Element nc) { 461 for (Extension e : nc.getExtension()) 462 if (e.getUrl().equals(EXT_DEPRECATED)) { 463 e.setValue(new BooleanType(true)); 464 return; 465 } 466 nc.getExtension().add(new Extension().setUrl(EXT_DEPRECATED).setValue(new BooleanType(true))); 467 } 468 469 public static void setExtension(Element focus, String url, Coding c) { 470 for (Extension e : focus.getExtension()) 471 if (e.getUrl().equals(url)) { 472 e.setValue(c); 473 return; 474 } 475 focus.getExtension().add(new Extension().setUrl(url).setValue(c)); 476 } 477 478 public static void removeExtension(DomainResource focus, String url) { 479 Iterator<Extension> i = focus.getExtension().iterator(); 480 while (i.hasNext()) { 481 Extension e = i.next(); // must be called before you can call i.remove() 482 if (e.getUrl().equals(url)) { 483 i.remove(); 484 } 485 } 486 } 487 488 public static void removeExtension(Element focus, String url) { 489 Iterator<Extension> i = focus.getExtension().iterator(); 490 while (i.hasNext()) { 491 Extension e = i.next(); // must be called before you can call i.remove() 492 if (e.getUrl().equals(url)) { 493 i.remove(); 494 } 495 } 496 } 497 498 499 public static void setStringExtension(Element element, String uri, String value) { 500 Extension ext = getExtension(element, uri); 501 if (ext != null) 502 ext.setValue(new StringType(value)); 503 else 504 element.getExtension().add(new Extension(new UriType(uri)).setValue(new StringType(value))); 505 } 506 507 508}