001package org.hl7.fhir.r5.renderers.utils;
002
003import java.io.IOException;
004import java.io.UnsupportedEncodingException;
005import java.util.ArrayList;
006import java.util.List;
007
008import org.hl7.fhir.r5.model.Base;
009import org.hl7.fhir.r5.model.CanonicalResource;
010import org.hl7.fhir.r5.model.DomainResource;
011import org.hl7.fhir.r5.model.ElementDefinition;
012import org.hl7.fhir.r5.model.Encounter;
013import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
014import org.hl7.fhir.r5.model.Patient;
015import org.hl7.fhir.r5.model.Property;
016import org.hl7.fhir.r5.model.Resource;
017import org.hl7.fhir.r5.model.StructureDefinition;
018import org.hl7.fhir.r5.renderers.EncounterRenderer;
019import org.hl7.fhir.r5.renderers.PatientRenderer;
020import org.hl7.fhir.r5.renderers.ResourceRenderer;
021import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
022import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
023import org.hl7.fhir.r5.renderers.utils.BaseWrappers.RendererWrapperImpl;
024import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
025import org.hl7.fhir.r5.renderers.utils.BaseWrappers.WrapperBaseImpl;
026import org.hl7.fhir.utilities.xhtml.XhtmlNode;
027
028public class DirectWrappers {
029
030  public static class PropertyWrapperDirect extends RendererWrapperImpl implements PropertyWrapper {
031    private Property wrapped;
032    private List<BaseWrapper> list;
033    private ElementDefinition ed;
034
035    public PropertyWrapperDirect(RenderingContext context, Property wrapped) {
036      super(context);
037      if (wrapped == null)
038        throw new Error("wrapped == null");
039      this.wrapped = wrapped;
040    }
041
042    public PropertyWrapperDirect(RenderingContext context, Property wrapped, ElementDefinition ed) {
043      super(context);
044      if (wrapped == null)
045        throw new Error("wrapped == null");
046      this.wrapped = wrapped;
047      this.ed = ed;
048    }
049
050    @Override
051    public String getName() {
052      return wrapped.getName();
053    }
054
055    public Property getWrapped() {
056      return wrapped;
057    }
058
059    @Override
060    public boolean hasValues() {
061      return wrapped.hasValues();
062    }
063
064    @Override
065    public List<BaseWrapper> getValues() {
066      if (list == null) {
067        list = new ArrayList<BaseWrapper>();
068        for (Base b : wrapped.getValues())
069          list.add(b == null ? null : new BaseWrapperDirect(context, b));
070      }
071      return list;
072    }
073
074    @Override
075    public String getTypeCode() {
076      return wrapped.getTypeCode();
077    }
078
079    @Override
080    public String getDefinition() {
081      return wrapped.getDefinition();
082    }
083
084    @Override
085    public int getMinCardinality() {
086      return wrapped.getMinCardinality();
087    }
088
089    @Override
090    public int getMaxCardinality() {
091      return wrapped.getMinCardinality();
092    }
093
094    @Override
095    public StructureDefinition getStructure() {
096      return wrapped.getStructure();
097    }
098
099    @Override
100    public BaseWrapper value() {
101      if (getValues().size() != 1)
102        throw new Error("Access single value, but value count is "+getValues().size());
103      return getValues().get(0);
104    }
105
106    public String toString() {
107      return "#."+wrapped.toString();
108    }
109
110    @Override
111    public ResourceWrapper getAsResource() {
112      throw new Error("Not implemented yet");
113    }
114
115    @Override
116    public String fhirType() {
117      return wrapped.getTypeCode();
118    }
119
120    @Override
121    public ElementDefinition getElementDefinition() {
122      return ed;
123    }
124  }
125
126  public static class BaseWrapperDirect extends WrapperBaseImpl implements BaseWrapper {
127    private Base wrapped;
128    private List<PropertyWrapper> list;
129
130    public BaseWrapperDirect(RenderingContext context, Base wrapped) {
131      super(context);
132      if (wrapped == null)
133        throw new Error("wrapped == null");
134      this.wrapped = wrapped;
135    }
136
137    @Override
138    public Base getBase() {
139      return wrapped;
140    }
141
142    @Override
143    public List<PropertyWrapper> children() {
144      if (list == null) {
145        list = new ArrayList<PropertyWrapper>();
146        for (Property p : wrapped.children())
147          list.add(new PropertyWrapperDirect(context, p));
148      }
149      return list;
150
151    }
152
153    @Override
154    public PropertyWrapper getChildByName(String name) {
155      Property p = wrapped.getChildByName(name);
156      if (p == null)
157        return null;
158      else
159        return new PropertyWrapperDirect(context, p);
160    }
161
162    @Override
163    public String fhirType() {
164      return wrapped.fhirType();
165    }
166
167  }
168
169  public static class ResourceWrapperDirect extends WrapperBaseImpl implements ResourceWrapper {
170    private Resource wrapped;
171
172    public ResourceWrapperDirect(RenderingContext context, Resource wrapped) {
173      super(context);
174      if (wrapped == null)
175        throw new Error("wrapped == null");
176      this.wrapped = wrapped;
177    }
178
179    @Override
180    public List<ResourceWrapper> getContained() {
181      List<ResourceWrapper> list = new ArrayList<ResourceWrapper>();
182      if (wrapped instanceof DomainResource) {
183        DomainResource dr = (DomainResource) wrapped;
184        for (Resource c : dr.getContained()) {
185          list.add(new ResourceWrapperDirect(context, c));
186        }
187      }
188      return list;
189    }
190
191    @Override
192    public String getId() {
193      return wrapped.getId();
194    }
195
196    @Override
197    public XhtmlNode getNarrative() {
198      if (wrapped instanceof DomainResource) {
199        DomainResource dr = (DomainResource) wrapped;
200        if (dr.hasText() && dr.getText().hasDiv())
201          return dr.getText().getDiv();
202      }
203      return null;
204    }
205
206    @Override
207    public String getName() {
208      return wrapped.getResourceType().toString();
209    }
210
211    @Override
212    public String getNameFromResource() {
213      Property name = wrapped.getChildByName("name");
214      if (name != null && name.hasValues()) {
215        Base b = name.getValues().get(0);
216        if (b.isPrimitive()) {
217          return b.primitiveValue();          
218        } else if (b.fhirType().equals("HumanName")) {
219          Property family = b.getChildByName("family");
220          Property given = wrapped.getChildByName("given");
221          String s = given != null && given.hasValues() ? given.getValues().get(0).primitiveValue() : "";
222          if (family != null && family.hasValues())
223            s = s + " " + family.getValues().get(0).primitiveValue().toUpperCase();
224          return s;
225        } else {
226          // it might be a human name?
227          throw new Error("What to do?");
228        }
229      }
230      return null;
231    }
232
233    @Override
234    public List<PropertyWrapper> children() {
235      List<PropertyWrapper> list = new ArrayList<PropertyWrapper>();
236      if (wrapped.children() != null) {
237        for (Property c : wrapped.children())
238          list.add(new PropertyWrapperDirect(context, c));
239      }
240      return list;
241    }
242
243    @Override
244    public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException {
245      if (wrapped instanceof CanonicalResource) {
246        x.tx(((CanonicalResource) wrapped).present());
247      } else if (wrapped instanceof Patient) {
248        new PatientRenderer(getContext()).describe(x, (Patient) wrapped);
249      } else if (wrapped instanceof Encounter) {
250        new EncounterRenderer(getContext()).describe(x, (Encounter) wrapped);
251      }
252    }
253
254    @Override
255    public void injectNarrative(XhtmlNode x, NarrativeStatus status) {
256      ResourceRenderer.inject((DomainResource) wrapped, x, status);
257      
258    }
259
260    @Override
261    public BaseWrapper root() {
262      return new BaseWrapperDirect(context, wrapped);
263    }
264
265    @Override
266    public StructureDefinition getDefinition() {
267      return context.getWorker().fetchTypeDefinition(wrapped.fhirType());
268    }
269
270    @Override
271    public Base getBase() {
272      return wrapped;
273    }
274
275    @Override
276    public boolean hasNarrative() {
277      StructureDefinition sd = context.getWorker().fetchTypeDefinition(wrapped.fhirType());
278      while (sd != null) {
279        if ("DomainResource".equals(sd.getType())) {
280          return true;
281        }
282        sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition());
283      }
284      return false;
285
286    }
287
288    @Override
289    public String fhirType() {
290      return wrapped.fhirType();
291    }
292    
293    @Override
294    public PropertyWrapper getChildByName(String name) {
295      Property p = wrapped.getChildByName(name);
296      if (p == null)
297        return null;
298      else
299        return new PropertyWrapperDirect(context, p);
300    }
301
302  }
303
304}