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