001package org.hl7.fhir.dstu2016may.metamodel;
002
003import org.hl7.fhir.dstu2016may.formats.FormatUtilities;
004import org.hl7.fhir.dstu2016may.model.ElementDefinition;
005import org.hl7.fhir.dstu2016may.model.ElementDefinition.TypeRefComponent;
006import org.hl7.fhir.dstu2016may.model.StructureDefinition;
007import org.hl7.fhir.dstu2016may.model.StructureDefinition.StructureDefinitionKind;
008import org.hl7.fhir.dstu2016may.utils.IWorkerContext;
009import org.hl7.fhir.dstu2016may.utils.ToolingExtensions;
010
011public class Property {
012
013        private IWorkerContext context;
014        private ElementDefinition definition;
015        private StructureDefinition structure;
016        private Boolean canBePrimitive; 
017
018        public Property(IWorkerContext context, ElementDefinition definition, StructureDefinition structure) {
019                this.context = context;
020                this.definition = definition;
021                this.structure = structure;
022        }
023
024        public String getName() {
025                return definition.getPath().substring(definition.getPath().lastIndexOf(".")+1);
026        }
027
028        public ElementDefinition getDefinition() {
029                return definition;
030        }
031
032        public String getType() {
033                if (definition.getType().size() == 0)
034                        return null;
035                else if (definition.getType().size() > 1) {
036                        String tn = definition.getType().get(0).getCode();
037                        for (int i = 1; i < definition.getType().size(); i++) {
038                                if (!tn.equals(definition.getType().get(i).getCode()))
039                        throw new Error("logic error, gettype when types > 1");
040                        }
041                        return tn;
042                } else
043                        return definition.getType().get(0).getCode();
044        }
045
046  public String getType(String elementName) {
047    if (definition.getType().size() == 0)
048      return null;
049    else if (definition.getType().size() > 1) {
050      String t = definition.getType().get(0).getCode();
051      boolean all = true;
052      for (TypeRefComponent tr : definition.getType()) {
053        if (!t.equals(tr.getCode()))
054          all = false;
055      }
056      if (all)
057        return t;
058      String tail = definition.getPath().substring(definition.getPath().lastIndexOf(".")+1);
059      if (tail.endsWith("[x]") && elementName != null && elementName.startsWith(tail.substring(0, tail.length()-3))) {
060        String name = elementName.substring(tail.length()-3);
061        return ParserBase.isPrimitive(lowFirst(name)) ? lowFirst(name) : name;        
062      } else
063        throw new Error("logic error, gettype when types > 1, name mismatch for "+elementName+" on at "+definition.getPath());
064    } else if (definition.getType().get(0).getCode() == null) {
065      return structure.getId();
066    } else
067      return definition.getType().get(0).getCode();
068  }
069
070  public boolean hasType(String elementName) {
071    if (definition.getType().size() == 0)
072      return false;
073    else if (definition.getType().size() > 1) {
074      String t = definition.getType().get(0).getCode();
075      boolean all = true;
076      for (TypeRefComponent tr : definition.getType()) {
077        if (!t.equals(tr.getCode()))
078          all = false;
079      }
080      if (all)
081        return true;
082      String tail = definition.getPath().substring(definition.getPath().lastIndexOf(".")+1);
083      if (tail.endsWith("[x]") && elementName.startsWith(tail.substring(0, tail.length()-3))) {
084        String name = elementName.substring(tail.length()-3);
085        return true;        
086      } else
087        return false;
088    } else
089      return true;
090  }
091
092        public StructureDefinition getStructure() {
093                return structure;
094        }
095
096        public boolean isPrimitive(String name) {
097    return ParserBase.isPrimitive(getType(name));
098        }
099
100        private String lowFirst(String t) {
101                return t.substring(0, 1).toLowerCase()+t.substring(1);
102        }
103
104        public boolean isResource() {
105                return definition.getType().size() == 1 && ("Resource".equals(definition.getType().get(0).getCode()) || "DomainResource".equals(definition.getType().get(0).getCode()));
106        }
107
108        public boolean isList() {
109          return !definition.getMax().equals("1");
110        }
111
112  public String getScopedPropertyName() {
113    return definition.getBase().getPath();
114  }
115
116  public String getNamespace() {
117    if (ToolingExtensions.hasExtension(definition, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"))
118      return ToolingExtensions.readStringExtension(definition, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace");
119    if (ToolingExtensions.hasExtension(structure, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"))
120      return ToolingExtensions.readStringExtension(structure, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace");
121    return FormatUtilities.FHIR_NS;
122  }
123
124        public boolean IsLogicalAndHasPrimitiveValue(String name) {
125                if (canBePrimitive!= null)
126                        return canBePrimitive;
127                
128                canBePrimitive = false;
129        if (structure.getKind() != StructureDefinitionKind.LOGICAL)
130                return false;
131        if (!hasType(name))
132                return false;
133        StructureDefinition sd = context.fetchResource(StructureDefinition.class, structure.getUrl().substring(0, structure.getUrl().lastIndexOf("/")+1)+getType(name));
134        if (sd == null || sd.getKind() != StructureDefinitionKind.LOGICAL)
135                return false;
136        for (ElementDefinition ed : sd.getSnapshot().getElement()) {
137                if (ed.getPath().equals(sd.getId()+".value") && ed.getType().size() == 1 && ParserBase.isPrimitive(ed.getType().get(0).getCode())) {
138                        canBePrimitive = true;
139                        return true;
140                }
141        }
142        return false;
143        }
144
145  public boolean isChoice() {
146    if (definition.getType().size() <= 1)
147      return false;
148    String tn = definition.getType().get(0).getCode();
149    for (int i = 1; i < definition.getType().size(); i++) 
150      if (!definition.getType().get(i).getCode().equals(tn))
151        return true;
152    return false;
153  }
154
155
156
157}