001package org.hl7.fhir.r4.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.IOException;
033import java.io.Serializable;
034import java.util.ArrayList;
035import java.util.HashMap;
036import java.util.List;
037import java.util.Map;
038
039import org.hl7.fhir.exceptions.FHIRException;
040import org.hl7.fhir.instance.model.api.IBase;
041import org.hl7.fhir.r4.elementmodel.Element;
042import org.hl7.fhir.r4.elementmodel.ObjectConverter;
043import org.hl7.fhir.utilities.Utilities;
044import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
045import org.hl7.fhir.utilities.xhtml.XhtmlNode;
046import org.hl7.fhir.utilities.xhtml.XhtmlParser;
047
048import ca.uhn.fhir.model.api.IElement;
049
050public abstract class Base implements Serializable, IBase, IElement {
051
052  /**
053   * User appended data items - allow users to add extra information to the class
054   */
055  private Map<String, Object> userData;
056
057  /**
058   * Round tracking xml comments for testing convenience
059   */
060  private List<String> formatCommentsPre;
061
062  /**
063   * Round tracking xml comments for testing convenience
064   */
065  private List<String> formatCommentsPost;
066
067  public Object getUserData(String name) {
068    if (userData == null)
069      return null;
070    return userData.get(name);
071  }
072
073  public void setUserData(String name, Object value) {
074    if (userData == null)
075      userData = new HashMap<String, Object>();
076    userData.put(name, value);
077  }
078
079  public void clearUserData(String name) {
080    if (userData != null)
081      userData.remove(name);
082  }
083
084  public void setUserDataINN(String name, Object value) {
085    if (value == null)
086      return;
087
088    if (userData == null)
089      userData = new HashMap<String, Object>();
090    userData.put(name, value);
091  }
092
093  public boolean hasUserData(String name) {
094    if (userData == null)
095      return false;
096    else
097      return userData.containsKey(name);
098  }
099
100  public String getUserString(String name) {
101    Object ud = getUserData(name);
102    if (ud == null)
103      return null;
104    if (ud instanceof String)
105      return (String) ud;
106    return ud.toString();
107  }
108
109  public int getUserInt(String name) {
110    if (!hasUserData(name))
111      return 0;
112    return (Integer) getUserData(name);
113  }
114
115  public boolean hasFormatComment() {
116    return (formatCommentsPre != null && !formatCommentsPre.isEmpty())
117        || (formatCommentsPost != null && !formatCommentsPost.isEmpty());
118  }
119
120  public List<String> getFormatCommentsPre() {
121    if (formatCommentsPre == null)
122      formatCommentsPre = new ArrayList<String>();
123    return formatCommentsPre;
124  }
125
126  public List<String> getFormatCommentsPost() {
127    if (formatCommentsPost == null)
128      formatCommentsPost = new ArrayList<String>();
129    return formatCommentsPost;
130  }
131
132  // these 3 allow evaluation engines to get access to primitive values
133  public boolean isPrimitive() {
134    return false;
135  }
136
137  public boolean isBooleanPrimitive() {
138    return false;
139  }
140
141  public boolean hasPrimitiveValue() {
142    return isPrimitive();
143  }
144
145  public String primitiveValue() {
146    return null;
147  }
148
149  public boolean isDateTime() {
150    return false;
151  }
152
153  public BaseDateTimeType dateTimeValue() {
154    return null;
155  }
156
157  public abstract String fhirType();
158
159  public boolean hasType(String... name) {
160    String t = fhirType();
161    for (String n : name)
162      if (n.equalsIgnoreCase(t))
163        return true;
164    return false;
165  }
166
167  protected abstract void listChildren(List<Property> result);
168
169  public Base setProperty(String name, Base value) throws FHIRException {
170    throw new FHIRException("Attempt to set unknown property " + name);
171  }
172
173  public Base addChild(String name) throws FHIRException {
174    throw new FHIRException("Attempt to add child with unknown name " + name);
175  }
176
177  /**
178   * Supports iterating the children elements in some generic processor or browser
179   * All defined children will be listed, even if they have no value on this
180   * instance
181   * 
182   * Note that the actual content of primitive or xhtml elements is not iterated
183   * explicitly. To find these, the processing code must recognise the element as
184   * a primitive, typecast the value to a {@link Type}, and examine the value
185   * 
186   * @return a list of all the children defined for this element
187   */
188  public List<Property> children() {
189    List<Property> result = new ArrayList<Property>();
190    listChildren(result);
191    return result;
192  }
193
194  public Property getChildByName(String name) {
195    List<Property> children = new ArrayList<Property>();
196    listChildren(children);
197    for (Property c : children)
198      if (c.getName().equals(name))
199        return c;
200    return null;
201  }
202
203  public List<Base> listChildrenByName(String name) throws FHIRException {
204    List<Base> result = new ArrayList<Base>();
205    for (Base b : listChildrenByName(name, true))
206      if (b != null)
207        result.add(b);
208    return result;
209  }
210
211  public Base[] listChildrenByName(String name, boolean checkValid) throws FHIRException {
212    if (name.equals("*")) {
213      List<Property> children = new ArrayList<Property>();
214      listChildren(children);
215      List<Base> result = new ArrayList<Base>();
216      for (Property c : children)
217        result.addAll(c.getValues());
218      return result.toArray(new Base[result.size()]);
219    } else
220      return getProperty(name.hashCode(), name, checkValid);
221  }
222
223  public boolean isEmpty() {
224    return true; // userData does not count
225  }
226
227  public boolean equalsDeep(Base other) {
228    return other != null;
229  }
230
231  public boolean equalsShallow(Base other) {
232    return other != null;
233  }
234
235  public static boolean compareDeep(String s1, String s2, boolean allowNull) {
236    if (allowNull) {
237      boolean noLeft = s1 == null || Utilities.noString(s1);
238      boolean noRight = s2 == null || Utilities.noString(s2);
239      if (noLeft && noRight) {
240        return true;
241      }
242    }
243    if (s1 == null || s2 == null)
244      return false;
245    return s1.equals(s2);
246  }
247
248  public static boolean compareDeep(List<? extends Base> e1, List<? extends Base> e2, boolean allowNull) {
249    if (noList(e1) && noList(e2) && allowNull)
250      return true;
251    if (noList(e1) || noList(e2))
252      return false;
253    if (e1.size() != e2.size())
254      return false;
255    for (int i = 0; i < e1.size(); i++) {
256      if (!compareDeep(e1.get(i), e2.get(i), allowNull))
257        return false;
258    }
259    return true;
260  }
261
262  private static boolean noList(List<? extends Base> list) {
263    return list == null || list.isEmpty();
264  }
265
266  public static boolean compareDeep(Base e1, Base e2, boolean allowNull) {
267    if (allowNull) {
268      boolean noLeft = e1 == null || e1.isEmpty();
269      boolean noRight = e2 == null || e2.isEmpty();
270      if (noLeft && noRight) {
271        return true;
272      }
273    }
274    if (e1 == null || e2 == null)
275      return false;
276    if (e2.isMetadataBased() && !e1.isMetadataBased()) // respect existing order for debugging consistency; outcome must
277                                                       // be the same either way
278      return e2.equalsDeep(e1);
279    else
280      return e1.equalsDeep(e2);
281  }
282
283  public static boolean compareDeep(XhtmlNode div1, XhtmlNode div2, boolean allowNull) {
284    if (div1 == null && div2 == null && allowNull)
285      return true;
286    if (div1 == null || div2 == null)
287      return false;
288    return div1.equalsDeep(div2);
289  }
290
291  public static boolean compareValues(List<? extends PrimitiveType> e1, List<? extends PrimitiveType> e2,
292      boolean allowNull) {
293    if (e1 == null && e2 == null && allowNull)
294      return true;
295    if (e1 == null || e2 == null)
296      return false;
297    if (e1.size() != e2.size())
298      return false;
299    for (int i = 0; i < e1.size(); i++) {
300      if (!compareValues(e1.get(i), e2.get(i), allowNull))
301        return false;
302    }
303    return true;
304  }
305
306  public static boolean compareValues(PrimitiveType e1, PrimitiveType e2, boolean allowNull) {
307    boolean noLeft = e1 == null || e1.isEmpty();
308    boolean noRight = e2 == null || e2.isEmpty();
309    if (noLeft && noRight && allowNull) {
310      return true;
311    }
312    if (noLeft != noRight)
313      return false;
314    return e1.equalsShallow(e2);
315  }
316
317  // -- converters for property setters
318
319  public Type castToType(Base b) throws FHIRException {
320    if (b == null) {
321      return null;
322    }
323    if (b instanceof Type)
324      return (Type) b;
325    else if (b.isMetadataBased())
326      return ((org.hl7.fhir.r4.elementmodel.Element) b).asType();
327    else
328      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Reference");
329  }
330
331  public BooleanType castToBoolean(Base b) throws FHIRException {
332    if (b == null) {
333      return null;
334    }
335    if (b instanceof BooleanType)
336      return (BooleanType) b;
337    else
338      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Boolean");
339  }
340
341  public IntegerType castToInteger(Base b) throws FHIRException {
342    if (b == null) {
343      return null;
344    }
345    if (b instanceof IntegerType)
346      return (IntegerType) b;
347    else
348      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Integer");
349  }
350
351  public DecimalType castToDecimal(Base b) throws FHIRException {
352    if (b == null) {
353      return null;
354    }
355    if (b instanceof DecimalType)
356      return (DecimalType) b;
357    else if (b.hasPrimitiveValue())
358      return new DecimalType(b.primitiveValue());
359    else
360      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Decimal");
361  }
362
363  public Base64BinaryType castToBase64Binary(Base b) throws FHIRException {
364    if (b == null) {
365      return null;
366    }
367    if (b instanceof Base64BinaryType)
368      return (Base64BinaryType) b;
369    else
370      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Base64Binary");
371  }
372
373  public InstantType castToInstant(Base b) throws FHIRException {
374    if (b == null) {
375      return null;
376    }
377    if (b instanceof InstantType)
378      return (InstantType) b;
379    else
380      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Instant");
381  }
382
383  public StringType castToString(Base b) throws FHIRException {
384    if (b == null) {
385      return null;
386    }
387    if (b instanceof StringType)
388      return (StringType) b;
389    else if (b.hasPrimitiveValue())
390      return new StringType(b.primitiveValue());
391    else
392      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a String");
393  }
394
395  public UriType castToUri(Base b) throws FHIRException {
396    if (b == null) {
397      return null;
398    }
399    if (b instanceof UriType)
400      return (UriType) b;
401    else if (b.hasPrimitiveValue())
402      return new UriType(b.primitiveValue());
403    else
404      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Uri");
405  }
406
407  public UrlType castToUrl(Base b) throws FHIRException {
408    if (b == null) {
409      return null;
410    }
411    if (b instanceof UrlType)
412      return (UrlType) b;
413    else if (b.hasPrimitiveValue())
414      return new UrlType(b.primitiveValue());
415    else
416      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Uri");
417  }
418
419  public CanonicalType castToCanonical(Base b) throws FHIRException {
420    if (b == null) {
421      return null;
422    }
423    if (b instanceof CanonicalType)
424      return (CanonicalType) b;
425    else if (b.hasPrimitiveValue())
426      return new CanonicalType(b.primitiveValue());
427    else
428      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Uri");
429  }
430
431  public DateType castToDate(Base b) throws FHIRException {
432    if (b == null) {
433      return null;
434    }
435    if (b instanceof DateType)
436      return (DateType) b;
437    else if (b.hasPrimitiveValue())
438      return new DateType(b.primitiveValue());
439    else
440      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Date");
441  }
442
443  public DateTimeType castToDateTime(Base b) throws FHIRException {
444    if (b == null) {
445      return null;
446    }
447    if (b instanceof DateTimeType)
448      return (DateTimeType) b;
449    else if (b.fhirType().equals("dateTime"))
450      return new DateTimeType(b.primitiveValue());
451    else
452      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a DateTime");
453  }
454
455  public TimeType castToTime(Base b) throws FHIRException {
456    if (b == null) {
457      return null;
458    }
459    if (b instanceof TimeType)
460      return (TimeType) b;
461    else
462      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Time");
463  }
464
465  public CodeType castToCode(Base b) throws FHIRException {
466    if (b == null) {
467      return null;
468    }
469    if (b instanceof CodeType)
470      return (CodeType) b;
471    else if (b instanceof PrimitiveType<?>)
472      return new CodeType(b.primitiveValue(), (PrimitiveType<?>) b);
473    else if (b.isPrimitive())
474      return new CodeType(b.primitiveValue());
475    else
476      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Code");
477  }
478
479  public OidType castToOid(Base b) throws FHIRException {
480    if (b == null) {
481      return null;
482    }
483    if (b instanceof OidType)
484      return (OidType) b;
485    else
486      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Oid");
487  }
488
489  public IdType castToId(Base b) throws FHIRException {
490    if (b == null) {
491      return null;
492    }
493    if (b instanceof IdType)
494      return (IdType) b;
495    else
496      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Id");
497  }
498
499  public UnsignedIntType castToUnsignedInt(Base b) throws FHIRException {
500    if (b == null) {
501      return null;
502    }
503    if (b instanceof UnsignedIntType)
504      return (UnsignedIntType) b;
505    else
506      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a UnsignedInt");
507  }
508
509  public PositiveIntType castToPositiveInt(Base b) throws FHIRException {
510    if (b == null) {
511      return null;
512    }
513    if (b instanceof PositiveIntType)
514      return (PositiveIntType) b;
515    else
516      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a PositiveInt");
517  }
518
519  public MarkdownType castToMarkdown(Base b) throws FHIRException {
520    if (b == null) {
521      return null;
522    }
523    if (b instanceof MarkdownType)
524      return (MarkdownType) b;
525    else if (b.hasPrimitiveValue())
526      return new MarkdownType(b.primitiveValue());
527    else
528      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Markdown");
529  }
530
531  public Annotation castToAnnotation(Base b) throws FHIRException {
532    if (b == null) {
533      return null;
534    }
535    if (b instanceof Annotation)
536      return (Annotation) b;
537    else
538      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an Annotation");
539  }
540
541  public Dosage castToDosage(Base b) throws FHIRException {
542    if (b == null) {
543      return null;
544    }
545    if (b instanceof Dosage)
546      return (Dosage) b;
547    else
548      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an DosageInstruction");
549  }
550
551  public Attachment castToAttachment(Base b) throws FHIRException {
552    if (b == null) {
553      return null;
554    }
555    if (b instanceof Attachment)
556      return (Attachment) b;
557    else
558      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an Attachment");
559  }
560
561  public Identifier castToIdentifier(Base b) throws FHIRException {
562    if (b == null) {
563      return null;
564    }
565    if (b instanceof Identifier)
566      return (Identifier) b;
567    else
568      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an Identifier");
569  }
570
571  public CodeableConcept castToCodeableConcept(Base b) throws FHIRException {
572    if (b == null) {
573      return null;
574    }
575    if (b instanceof CodeableConcept)
576      return (CodeableConcept) b;
577    else if (b instanceof Element) {
578      return ObjectConverter.readAsCodeableConcept((Element) b);
579    } else if (b instanceof CodeType) {
580      CodeableConcept cc = new CodeableConcept();
581      cc.addCoding().setCode(((CodeType) b).asStringValue());
582      return cc;
583    } else
584      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a CodeableConcept");
585  }
586
587  public Population castToPopulation(Base b) throws FHIRException {
588    if (b == null) {
589      return null;
590    }
591    if (b instanceof Population)
592      return (Population) b;
593    else
594      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Population");
595  }
596
597  public Coding castToCoding(Base b) throws FHIRException {
598    if (b == null) {
599      return null;
600    }
601    if (b instanceof Coding)
602      return (Coding) b;
603    else if (b instanceof Element) {
604      ICoding c = ((Element) b).getAsICoding();
605      if (c == null)
606        throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Coding");
607      return new Coding().setCode(c.getCode()).setSystem(c.getSystem()).setVersion(c.getVersion())
608          .setDisplay(c.getDisplay());
609    } else if (b instanceof ICoding) {
610      ICoding c = (ICoding) b;
611      return new Coding().setCode(c.getCode()).setSystem(c.getSystem()).setVersion(c.getVersion())
612          .setDisplay(c.getDisplay());
613    } else
614      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Coding");
615  }
616
617  public Quantity castToQuantity(Base b) throws FHIRException {
618    if (b == null) {
619      return null;
620    }
621    if (b instanceof Quantity)
622      return (Quantity) b;
623    else
624      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an Quantity");
625  }
626
627  public Money castToMoney(Base b) throws FHIRException {
628    if (b == null) {
629      return null;
630    }
631    if (b instanceof Money)
632      return (Money) b;
633    else
634      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an Money");
635  }
636
637  public Duration castToDuration(Base b) throws FHIRException {
638    if (b == null) {
639      return null;
640    }
641    if (b instanceof Duration)
642      return (Duration) b;
643    else
644      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an Duration");
645  }
646
647  public SimpleQuantity castToSimpleQuantity(Base b) throws FHIRException {
648    if (b == null) {
649      return null;
650    }
651    if (b instanceof SimpleQuantity)
652      return (SimpleQuantity) b;
653    else if (b instanceof Quantity) {
654      Quantity q = (Quantity) b;
655      SimpleQuantity sq = new SimpleQuantity();
656      sq.setValueElement(q.getValueElement());
657      sq.setComparatorElement(q.getComparatorElement());
658      sq.setUnitElement(q.getUnitElement());
659      sq.setSystemElement(q.getSystemElement());
660      sq.setCodeElement(q.getCodeElement());
661      return sq;
662    } else
663      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to an SimpleQuantity");
664  }
665
666  public Range castToRange(Base b) throws FHIRException {
667    if (b == null) {
668      return null;
669    }
670    if (b instanceof Range)
671      return (Range) b;
672    else
673      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Range");
674  }
675
676  public Period castToPeriod(Base b) throws FHIRException {
677    if (b == null) {
678      return null;
679    }
680    if (b instanceof Period)
681      return (Period) b;
682    else
683      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Period");
684  }
685
686  public Ratio castToRatio(Base b) throws FHIRException {
687    if (b == null) {
688      return null;
689    }
690    if (b instanceof Ratio)
691      return (Ratio) b;
692    else
693      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Ratio");
694  }
695
696  public SampledData castToSampledData(Base b) throws FHIRException {
697    if (b == null) {
698      return null;
699    }
700    if (b instanceof SampledData)
701      return (SampledData) b;
702    else
703      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a SampledData");
704  }
705
706  public Signature castToSignature(Base b) throws FHIRException {
707    if (b == null) {
708      return null;
709    }
710    if (b instanceof Signature)
711      return (Signature) b;
712    else
713      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Signature");
714  }
715
716  public HumanName castToHumanName(Base b) throws FHIRException {
717    if (b == null) {
718      return null;
719    }
720    if (b instanceof HumanName)
721      return (HumanName) b;
722    else
723      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a HumanName");
724  }
725
726  public Address castToAddress(Base b) throws FHIRException {
727    if (b == null) {
728      return null;
729    }
730    if (b instanceof Address)
731      return (Address) b;
732    else
733      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Address");
734  }
735
736  public ContactDetail castToContactDetail(Base b) throws FHIRException {
737    if (b == null) {
738      return null;
739    }
740    if (b instanceof ContactDetail)
741      return (ContactDetail) b;
742    else
743      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a ContactDetail");
744  }
745
746  public Contributor castToContributor(Base b) throws FHIRException {
747    if (b == null) {
748      return null;
749    }
750    if (b instanceof Contributor)
751      return (Contributor) b;
752    else
753      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Contributor");
754  }
755
756  public UsageContext castToUsageContext(Base b) throws FHIRException {
757    if (b == null) {
758      return null;
759    }
760    if (b instanceof UsageContext)
761      return (UsageContext) b;
762    else
763      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a UsageContext");
764  }
765
766  public RelatedArtifact castToRelatedArtifact(Base b) throws FHIRException {
767    if (b == null) {
768      return null;
769    }
770    if (b instanceof RelatedArtifact)
771      return (RelatedArtifact) b;
772    else
773      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a RelatedArtifact");
774  }
775
776  public ContactPoint castToContactPoint(Base b) throws FHIRException {
777    if (b == null) {
778      return null;
779    }
780    if (b instanceof ContactPoint)
781      return (ContactPoint) b;
782    else
783      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a ContactPoint");
784  }
785
786  public Timing castToTiming(Base b) throws FHIRException {
787    if (b == null) {
788      return null;
789    }
790    if (b instanceof Timing)
791      return (Timing) b;
792    else
793      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Timing");
794  }
795
796  public Reference castToReference(Base b) throws FHIRException {
797    if (b == null) {
798      return null;
799    }
800    if (b instanceof Reference)
801      return (Reference) b;
802    else if (b.isPrimitive() && Utilities.isURL(b.primitiveValue()))
803      return new Reference().setReference(b.primitiveValue());
804    else if (b instanceof org.hl7.fhir.r4.elementmodel.Element && b.fhirType().equals("Reference")) {
805      org.hl7.fhir.r4.elementmodel.Element e = (org.hl7.fhir.r4.elementmodel.Element) b;
806      return new Reference().setReference(e.getChildValue("reference")).setDisplay(e.getChildValue("display"));
807    } else
808      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Reference");
809  }
810
811  public Meta castToMeta(Base b) throws FHIRException {
812    if (b == null) {
813      return null;
814    }
815    if (b instanceof Meta)
816      return (Meta) b;
817    else
818      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Meta");
819  }
820
821  public MarketingStatus castToMarketingStatus(Base b) throws FHIRException {
822    if (b == null) {
823      return null;
824    }
825    if (b instanceof MarketingStatus)
826      return (MarketingStatus) b;
827    else
828      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a MarketingStatus");
829  }
830
831  public ProductShelfLife castToProductShelfLife(Base b) throws FHIRException {
832    if (b == null) {
833      return null;
834    }
835    if (b instanceof ProductShelfLife)
836      return (ProductShelfLife) b;
837    else
838      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a ProductShelfLife");
839  }
840
841  public ProdCharacteristic castToProdCharacteristic(Base b) throws FHIRException {
842    if (b == null) {
843      return null;
844    }
845    if (b instanceof ProdCharacteristic)
846      return (ProdCharacteristic) b;
847    else
848      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a ProdCharacteristic");
849  }
850
851  public SubstanceAmount castToSubstanceAmount(Base b) throws FHIRException {
852    if (b == null) {
853      return null;
854    }
855    if (b instanceof SubstanceAmount)
856      return (SubstanceAmount) b;
857    else
858      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a SubstanceAmount");
859  }
860
861  public Extension castToExtension(Base b) throws FHIRException {
862    if (b == null) {
863      return null;
864    }
865    if (b instanceof Extension)
866      return (Extension) b;
867    else
868      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Extension");
869  }
870
871  public Resource castToResource(Base b) throws FHIRException {
872    if (b == null) {
873      return null;
874    }
875    if (b instanceof Resource)
876      return (Resource) b;
877    else
878      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Resource");
879  }
880
881  public Narrative castToNarrative(Base b) throws FHIRException {
882    if (b == null) {
883      return null;
884    }
885    if (b instanceof Narrative)
886      return (Narrative) b;
887    else
888      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Narrative");
889  }
890
891  public ElementDefinition castToElementDefinition(Base b) throws FHIRException {
892    if (b == null) {
893      return null;
894    }
895    if (b instanceof ElementDefinition)
896      return (ElementDefinition) b;
897    else
898      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a ElementDefinition");
899  }
900
901  public DataRequirement castToDataRequirement(Base b) throws FHIRException {
902    if (b == null) {
903      return null;
904    }
905    if (b instanceof DataRequirement)
906      return (DataRequirement) b;
907    else
908      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a DataRequirement");
909  }
910
911  public Expression castToExpression(Base b) throws FHIRException {
912    if (b == null) {
913      return null;
914    }
915    if (b instanceof Expression)
916      return (Expression) b;
917    else
918      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a Expression");
919  }
920
921  public ParameterDefinition castToParameterDefinition(Base b) throws FHIRException {
922    if (b == null) {
923      return null;
924    }
925    if (b instanceof ParameterDefinition)
926      return (ParameterDefinition) b;
927    else
928      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a ParameterDefinition");
929  }
930
931  public TriggerDefinition castToTriggerDefinition(Base b) throws FHIRException {
932    if (b == null) {
933      return null;
934    }
935    if (b instanceof TriggerDefinition)
936      return (TriggerDefinition) b;
937    else
938      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to a TriggerDefinition");
939  }
940
941  public XhtmlNode castToXhtml(Base b) throws FHIRException {
942    if (b == null) {
943      return null;
944    }
945    if (b instanceof Element) {
946      return ((Element) b).getXhtml();
947    } else if (b instanceof XhtmlType) {
948      return ((XhtmlType) b).getValue();
949    } else if (b instanceof StringType) {
950      try {
951        return new XhtmlParser().parseFragment(((StringType) b).asStringValue());
952      } catch (IOException e) {
953        throw new FHIRException(e);
954      }
955    } else
956      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to XHtml");
957  }
958
959  public String castToXhtmlString(Base b) throws FHIRException {
960    if (b == null) {
961      return null;
962    }
963    if (b instanceof Element) {
964      return ((Element) b).getValue();
965    } else if (b instanceof XhtmlType) {
966      try {
967        return new XhtmlComposer(true).compose(((XhtmlType) b).getValue());
968      } catch (IOException e) {
969        return null;
970      }
971    } else if (b instanceof StringType) {
972      return ((StringType) b).asStringValue();
973    } else
974      throw new FHIRException("Unable to convert a " + b.getClass().getName() + " to XHtml string");
975  }
976
977  protected boolean isMetadataBased() {
978    return false;
979  }
980
981  public Base[] getProperty(int hash, String name, boolean checkValid) throws FHIRException {
982    if (checkValid)
983      throw new FHIRException("Attempt to read invalid property '" + name + "' on type " + fhirType());
984    return null;
985  }
986
987  public Base setProperty(int hash, String name, Base value) throws FHIRException {
988    throw new FHIRException("Attempt to write to invalid property '" + name + "' on type " + fhirType());
989  }
990
991  public Base makeProperty(int hash, String name) throws FHIRException {
992    throw new FHIRException("Attempt to make an invalid property '" + name + "' on type " + fhirType());
993  }
994
995  public String[] getTypesForProperty(int hash, String name) throws FHIRException {
996    throw new FHIRException("Attempt to get types for an invalid property '" + name + "' on type " + fhirType());
997  }
998
999  public static boolean equals(String v1, String v2) {
1000    if (v1 == null && v2 == null)
1001      return true;
1002    else if (v1 == null || v2 == null)
1003      return false;
1004    else
1005      return v1.equals(v2);
1006  }
1007
1008  public boolean isResource() {
1009    return false;
1010  }
1011
1012  public abstract String getIdBase();
1013
1014  public abstract void setIdBase(String value);
1015
1016  public Property getNamedProperty(String _name) throws FHIRException {
1017    return getNamedProperty(_name.hashCode(), _name, false);
1018  }
1019
1020  public Property getNamedProperty(int _hash, String _name, boolean _checkValid) throws FHIRException {
1021    if (_checkValid)
1022      throw new FHIRException("Attempt to read invalid property '" + _name + "' on type " + fhirType());
1023    return null;
1024  }
1025
1026  public XhtmlNode getXhtml() {
1027    return null;
1028  }
1029
1030  public abstract Base copy();
1031
1032  public void copyValues(Base dst) {
1033  }
1034
1035}