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