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