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