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