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