001package org.hl7.fhir.dstu2016may.model; 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.io.Serializable; 035import java.util.ArrayList; 036import java.util.HashMap; 037import java.util.List; 038import java.util.Map; 039 040import org.hl7.fhir.exceptions.FHIRException; 041import org.hl7.fhir.instance.model.api.IBase; 042import org.hl7.fhir.utilities.xhtml.XhtmlNode; 043 044import ca.uhn.fhir.model.api.IElement; 045 046public abstract class Base implements Serializable, IBase, IElement { 047 048 /** 049 * User appended data items - allow users to add extra information to the class 050 */ 051private Map<String, Object> userData; 052 053 /** 054 * Round tracking xml comments for testing convenience 055 */ 056 private List<String> formatCommentsPre; 057 058 /** 059 * Round tracking xml comments for testing convenience 060 */ 061 private List<String> formatCommentsPost; 062 063 064 public Object getUserData(String name) { 065 if (userData == null) 066 return null; 067 return userData.get(name); 068 } 069 070 public void setUserData(String name, Object value) { 071 if (userData == null) 072 userData = new HashMap<String, Object>(); 073 userData.put(name, value); 074 } 075 076 public void setUserDataINN(String name, Object value) { 077 if (value == null) 078 return; 079 080 if (userData == null) 081 userData = new HashMap<String, Object>(); 082 userData.put(name, value); 083 } 084 085 public boolean hasUserData(String name) { 086 if (userData == null) 087 return false; 088 else 089 return userData.containsKey(name); 090 } 091 092 public String getUserString(String name) { 093 return (String) getUserData(name); 094 } 095 096 public int getUserInt(String name) { 097 if (!hasUserData(name)) 098 return 0; 099 return (Integer) getUserData(name); 100 } 101 102 public boolean hasFormatComment() { 103 return (formatCommentsPre != null && !formatCommentsPre.isEmpty()) || (formatCommentsPost != null && !formatCommentsPost.isEmpty()); 104 } 105 106 public List<String> getFormatCommentsPre() { 107 if (formatCommentsPre == null) 108 formatCommentsPre = new ArrayList<String>(); 109 return formatCommentsPre; 110 } 111 112 public List<String> getFormatCommentsPost() { 113 if (formatCommentsPost == null) 114 formatCommentsPost = new ArrayList<String>(); 115 return formatCommentsPost; 116 } 117 118 // these 3 allow evaluation engines to get access to primitive values 119 public boolean isPrimitive() { 120 return false; 121 } 122 123 public boolean hasPrimitiveValue() { 124 return isPrimitive(); 125 } 126 127 public String primitiveValue() { 128 return null; 129 } 130 131 public abstract String fhirType() ; 132 133 public boolean hasType(String... name) { 134 String t = fhirType(); 135 for (String n : name) 136 if (n.equals(t)) 137 return true; 138 return false; 139 } 140 141 protected abstract void listChildren(List<Property> result) ; 142 143 public void setProperty(String name, Base value) throws FHIRException { 144 throw new FHIRException("Attempt to set unknown property "+name); 145 } 146 147 public Base addChild(String name) throws FHIRException { 148 throw new FHIRException("Attempt to add child with unknown name "+name); 149 } 150 151 /** 152 * Supports iterating the children elements in some generic processor or browser 153 * All defined children will be listed, even if they have no value on this instance 154 * 155 * Note that the actual content of primitive or xhtml elements is not iterated explicitly. 156 * To find these, the processing code must recognise the element as a primitive, typecast 157 * the value to a {@link Type}, and examine the value 158 * 159 * @return a list of all the children defined for this element 160 */ 161 public List<Property> children() { 162 List<Property> result = new ArrayList<Property>(); 163 listChildren(result); 164 return result; 165 } 166 167 public Property getChildByName(String name) { 168 List<Property> children = new ArrayList<Property>(); 169 listChildren(children); 170 for (Property c : children) 171 if (c.getName().equals(name)) 172 return c; 173 return null; 174 } 175 176 public List<Base> listChildrenByName(String name) throws FHIRException { 177 List<Base> result = new ArrayList<Base>(); 178 for (Base b : listChildrenByName(name, true)) 179 if (b != null) 180 result.add(b); 181 return result; 182 } 183 184 public Base[] listChildrenByName(String name, boolean checkValid) throws FHIRException { 185 if (name.equals("*")) { 186 List<Property> children = new ArrayList<Property>(); 187 listChildren(children); 188 List<Base> result = new ArrayList<Base>(); 189 for (Property c : children) 190 if (name.equals("*") || c.getName().equals(name) || (c.getName().endsWith("[x]") && c.getName().startsWith(name))) 191 result.addAll(c.getValues()); 192 return result.toArray(new Base[result.size()]); 193 } 194 else 195 return getProperty(name.hashCode(), name, checkValid); 196 } 197 198 public boolean isEmpty() { 199 return true; // userData does not count 200 } 201 202 public boolean equalsDeep(Base other) { 203 return other == this; 204 } 205 206 public boolean equalsShallow(Base other) { 207 return other == this; 208 } 209 210 public static boolean compareDeep(List<? extends Base> e1, List<? extends Base> e2, boolean allowNull) { 211 if (noList(e1) && noList(e2) && allowNull) 212 return true; 213 if (noList(e1) || noList(e2)) 214 return false; 215 if (e1.size() != e2.size()) 216 return false; 217 for (int i = 0; i < e1.size(); i++) { 218 if (!compareDeep(e1.get(i), e2.get(i), allowNull)) 219 return false; 220 } 221 return true; 222 } 223 224 private static boolean noList(List<? extends Base> list) { 225 return list == null || list.isEmpty(); 226 } 227 228 public static boolean compareDeep(Base e1, Base e2, boolean allowNull) { 229 if (e1 == null && e2 == null && allowNull) 230 return true; 231 if (e1 == null || e2 == null) 232 return false; 233 if (e2.isMetadataBased() && !e1.isMetadataBased()) // respect existing order for debugging consistency; outcome must be the same either way 234 return e2.equalsDeep(e1); 235 else 236 return e1.equalsDeep(e2); 237 } 238 239 public static boolean compareDeep(XhtmlNode div1, XhtmlNode div2, boolean allowNull) { 240 if (div1 == null && div2 == null && allowNull) 241 return true; 242 if (div1 == null || div2 == null) 243 return false; 244 return div1.equalsDeep(div2); 245 } 246 247 248 public static boolean compareValues(List<? extends PrimitiveType> e1, List<? extends PrimitiveType> e2, boolean allowNull) { 249 if (e1 == null && e2 == null && allowNull) 250 return true; 251 if (e1 == null || e2 == null) 252 return false; 253 if (e1.size() != e2.size()) 254 return false; 255 for (int i = 0; i < e1.size(); i++) { 256 if (!compareValues(e1.get(i), e2.get(i), allowNull)) 257 return false; 258 } 259 return true; 260 } 261 262 public static boolean compareValues(PrimitiveType e1, PrimitiveType e2, boolean allowNull) { 263 if (e1 == null && e2 == null && allowNull) 264 return true; 265 if (e1 == null || e2 == null) 266 return false; 267 return e1.equalsShallow(e2); 268 } 269 270 // -- converters for property setters 271 272 273 public BooleanType castToBoolean(Base b) throws FHIRException { 274 if (b instanceof BooleanType) 275 return (BooleanType) b; 276 else 277 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Boolean"); 278 } 279 280 public IntegerType castToInteger(Base b) throws FHIRException { 281 if (b instanceof IntegerType) 282 return (IntegerType) b; 283 else 284 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Integer"); 285 } 286 287 public DecimalType castToDecimal(Base b) throws FHIRException { 288 if (b instanceof DecimalType) 289 return (DecimalType) b; 290 else 291 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Decimal"); 292 } 293 294 public Base64BinaryType castToBase64Binary(Base b) throws FHIRException { 295 if (b instanceof Base64BinaryType) 296 return (Base64BinaryType) b; 297 else 298 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Base64Binary"); 299 } 300 301 public InstantType castToInstant(Base b) throws FHIRException { 302 if (b instanceof InstantType) 303 return (InstantType) b; 304 else 305 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Instant"); 306 } 307 308 public StringType castToString(Base b) throws FHIRException { 309 if (b instanceof StringType) 310 return (StringType) b; 311 else if (b.hasPrimitiveValue()) 312 return new StringType(b.primitiveValue()); 313 else 314 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a String"); 315 } 316 317 public UriType castToUri(Base b) throws FHIRException { 318 if (b instanceof UriType) 319 return (UriType) b; 320 else if (b.hasPrimitiveValue()) 321 return new UriType(b.primitiveValue()); 322 else 323 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Uri"); 324 } 325 326 public DateType castToDate(Base b) throws FHIRException { 327 if (b instanceof DateType) 328 return (DateType) b; 329 else if (b.hasPrimitiveValue()) 330 return new DateType(b.primitiveValue()); 331 else 332 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Date"); 333 } 334 335 public DateTimeType castToDateTime(Base b) throws FHIRException { 336 if (b instanceof DateTimeType) 337 return (DateTimeType) b; 338 else if (b.fhirType().equals("dateTime")) 339 return new DateTimeType(b.primitiveValue()); 340 else 341 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a DateTime"); 342 } 343 344 public TimeType castToTime(Base b) throws FHIRException { 345 if (b instanceof TimeType) 346 return (TimeType) b; 347 else 348 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Time"); 349 } 350 351 public CodeType castToCode(Base b) throws FHIRException { 352 if (b instanceof CodeType) 353 return (CodeType) b; 354 else if (b.isPrimitive()) 355 return new CodeType(b.primitiveValue()); 356 else 357 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Code"); 358 } 359 360 public OidType castToOid(Base b) throws FHIRException { 361 if (b instanceof OidType) 362 return (OidType) b; 363 else 364 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Oid"); 365 } 366 367 public IdType castToId(Base b) throws FHIRException { 368 if (b instanceof IdType) 369 return (IdType) b; 370 else 371 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Id"); 372 } 373 374 public UnsignedIntType castToUnsignedInt(Base b) throws FHIRException { 375 if (b instanceof UnsignedIntType) 376 return (UnsignedIntType) b; 377 else 378 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a UnsignedInt"); 379 } 380 381 public PositiveIntType castToPositiveInt(Base b) throws FHIRException { 382 if (b instanceof PositiveIntType) 383 return (PositiveIntType) b; 384 else 385 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a PositiveInt"); 386 } 387 388 public MarkdownType castToMarkdown(Base b) throws FHIRException { 389 if (b instanceof MarkdownType) 390 return (MarkdownType) b; 391 else 392 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Markdown"); 393 } 394 395 public Annotation castToAnnotation(Base b) throws FHIRException { 396 if (b instanceof Annotation) 397 return (Annotation) b; 398 else 399 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an Annotation"); 400 } 401 402 public Attachment castToAttachment(Base b) throws FHIRException { 403 if (b instanceof Attachment) 404 return (Attachment) b; 405 else 406 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an Attachment"); 407 } 408 409 public Identifier castToIdentifier(Base b) throws FHIRException { 410 if (b instanceof Identifier) 411 return (Identifier) b; 412 else 413 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an Identifier"); 414 } 415 416 public CodeableConcept castToCodeableConcept(Base b) throws FHIRException { 417 if (b instanceof CodeableConcept) 418 return (CodeableConcept) b; 419 else if (b instanceof CodeType) { 420 CodeableConcept cc = new CodeableConcept(); 421 cc.addCoding().setCode(((CodeType) b).asStringValue()); 422 return cc; 423 } else 424 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a CodeableConcept"); 425 } 426 427 public Coding castToCoding(Base b) throws FHIRException { 428 if (b instanceof Coding) 429 return (Coding) b; 430 else 431 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Coding"); 432 } 433 434 public Quantity castToQuantity(Base b) throws FHIRException { 435 if (b instanceof Quantity) 436 return (Quantity) b; 437 else 438 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an Quantity"); 439 } 440 441 public Money castToMoney(Base b) throws FHIRException { 442 if (b instanceof Money) 443 return (Money) b; 444 else 445 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an Money"); 446 } 447 448 public Duration castToDuration(Base b) throws FHIRException { 449 if (b instanceof Duration) 450 return (Duration) b; 451 else 452 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an Duration"); 453 } 454 455 public SimpleQuantity castToSimpleQuantity(Base b) throws FHIRException { 456 if (b instanceof SimpleQuantity) 457 return (SimpleQuantity) b; 458 else if (b instanceof Quantity) { 459 Quantity q = (Quantity) b; 460 SimpleQuantity sq = new SimpleQuantity(); 461 sq.setValueElement(q.getValueElement()); 462 sq.setComparatorElement(q.getComparatorElement()); 463 sq.setUnitElement(q.getUnitElement()); 464 sq.setSystemElement(q.getSystemElement()); 465 sq.setCodeElement(q.getCodeElement()); 466 return sq; 467 } else 468 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to an SimpleQuantity"); 469 } 470 471 public Range castToRange(Base b) throws FHIRException { 472 if (b instanceof Range) 473 return (Range) b; 474 else 475 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Range"); 476 } 477 478 public Period castToPeriod(Base b) throws FHIRException { 479 if (b instanceof Period) 480 return (Period) b; 481 else 482 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Period"); 483 } 484 485 public Ratio castToRatio(Base b) throws FHIRException { 486 if (b instanceof Ratio) 487 return (Ratio) b; 488 else 489 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Ratio"); 490 } 491 492 public SampledData castToSampledData(Base b) throws FHIRException { 493 if (b instanceof SampledData) 494 return (SampledData) b; 495 else 496 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a SampledData"); 497 } 498 499 public Signature castToSignature(Base b) throws FHIRException { 500 if (b instanceof Signature) 501 return (Signature) b; 502 else 503 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Signature"); 504 } 505 506 public HumanName castToHumanName(Base b) throws FHIRException { 507 if (b instanceof HumanName) 508 return (HumanName) b; 509 else 510 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a HumanName"); 511 } 512 513 public Address castToAddress(Base b) throws FHIRException { 514 if (b instanceof Address) 515 return (Address) b; 516 else 517 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Address"); 518 } 519 520 public ContactPoint castToContactPoint(Base b) throws FHIRException { 521 if (b instanceof ContactPoint) 522 return (ContactPoint) b; 523 else 524 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a ContactPoint"); 525 } 526 527 public Timing castToTiming(Base b) throws FHIRException { 528 if (b instanceof Timing) 529 return (Timing) b; 530 else 531 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Timing"); 532 } 533 534 public Reference castToReference(Base b) throws FHIRException { 535 if (b instanceof Reference) 536 return (Reference) b; 537 else 538 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Reference"); 539 } 540 541 public Meta castToMeta(Base b) throws FHIRException { 542 if (b instanceof Meta) 543 return (Meta) b; 544 else 545 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Meta"); 546 } 547 548 public Extension castToExtension(Base b) throws FHIRException { 549 if (b instanceof Extension) 550 return (Extension) b; 551 else 552 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Extension"); 553 } 554 555 public Resource castToResource(Base b) throws FHIRException { 556 if (b instanceof Resource) 557 return (Resource) b; 558 else 559 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Resource"); 560 } 561 562 public Narrative castToNarrative(Base b) throws FHIRException { 563 if (b instanceof Narrative) 564 return (Narrative) b; 565 else 566 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a Narrative"); 567 } 568 569 570 public ElementDefinition castToElementDefinition(Base b) throws FHIRException { 571 if (b instanceof ElementDefinition) 572 return (ElementDefinition) b; 573 else 574 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a ElementDefinition"); 575 } 576 577 public ModuleMetadata castToModuleMetadata(Base b) throws FHIRException { 578 if (b instanceof ModuleMetadata) 579 return (ModuleMetadata) b; 580 else 581 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a ModuleMetadata"); 582 } 583 584 public ActionDefinition castToActionDefinition(Base b) throws FHIRException { 585 if (b instanceof ActionDefinition) 586 return (ActionDefinition) b; 587 else 588 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a ActionDefinition"); 589 } 590 591 public DataRequirement castToDataRequirement(Base b) throws FHIRException { 592 if (b instanceof DataRequirement) 593 return (DataRequirement) b; 594 else 595 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a DataRequirement"); 596 } 597 598 public ParameterDefinition castToParameterDefinition(Base b) throws FHIRException { 599 if (b instanceof ParameterDefinition) 600 return (ParameterDefinition) b; 601 else 602 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a ParameterDefinition"); 603 } 604 605 public TriggerDefinition castToTriggerDefinition(Base b) throws FHIRException { 606 if (b instanceof TriggerDefinition) 607 return (TriggerDefinition) b; 608 else 609 throw new FHIRException("Unable to convert a "+b.getClass().getName()+" to a TriggerDefinition"); 610 } 611 612 protected boolean isMetadataBased() { 613 return false; 614 } 615 616 public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException { 617 if (checkValid) 618 throw new FHIRException("Attempt to read invalid property '"+name+"' on type "+fhirType()); 619 return null; 620 } 621 622 public void setProperty(int hash, String name, Base value) throws FHIRException { 623 throw new FHIRException("Attempt to write to invalid property '"+name+"' on type "+fhirType()); 624 } 625 626 /** 627 * make an instance of a property. If the property is a repeating property, make a new instance. if the property is not repeating, return the property 628 * 629 * @param hash 630 * @param name 631 * @return 632 * @throws FHIRException 633 */ 634 public Base makeProperty(int hash, String name) throws FHIRException { 635 throw new FHIRException("Attempt to make an invalid property '"+name+"' on type "+fhirType()); 636 } 637 638 public static boolean equals(String v1, String v2) { 639 if (v1 == null && v2 == null) 640 return true; 641 else if (v1 == null || v2 == null) 642 return false; 643 else 644 return v1.equals(v2); 645 } 646 647 648}