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