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