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          Property p = b.getChildByName("name");
227          if (p == null || !p.hasValues()) {            
228            p = b.getChildByName("name");
229          }
230          if (p == null || !p.hasValues()) {            
231            p = b.getChildByName("text");
232          }
233          if (p == null || !p.hasValues()) {            
234            p = b.getChildByName("value");
235          }
236          if (p == null || !p.hasValues()) {            
237            p = b.getChildByName("productName"); // MedicinalProductDefinition
238          }
239          if (p == null || !p.hasValues()) {            
240            throw new Error("What to render for 'name'? Type is "+b.fhirType());
241          } else {
242            return p.getValues().get(0).primitiveValue();            
243          }
244        }
245      }
246      return null;
247    }
248
249    @Override
250    public List<PropertyWrapper> children() {
251      List<PropertyWrapper> list = new ArrayList<PropertyWrapper>();
252      if (wrapped.children() != null) {
253        for (Property c : wrapped.children())
254          list.add(new PropertyWrapperDirect(context, c));
255      }
256      return list;
257    }
258
259    @Override
260    public void describe(XhtmlNode x) throws UnsupportedEncodingException, IOException {
261      if (wrapped instanceof CanonicalResource) {
262        x.tx(((CanonicalResource) wrapped).present());
263      } else if (wrapped instanceof Patient) {
264        new PatientRenderer(getContext()).describe(x, (Patient) wrapped);
265      } else if (wrapped instanceof Encounter) {
266        new EncounterRenderer(getContext()).describe(x, (Encounter) wrapped);
267      }
268    }
269
270    @Override
271    public void injectNarrative(XhtmlNode x, NarrativeStatus status) {
272      ResourceRenderer.inject((DomainResource) wrapped, x, status);
273      
274    }
275
276    @Override
277    public BaseWrapper root() {
278      return new BaseWrapperDirect(context, wrapped);
279    }
280
281    @Override
282    public StructureDefinition getDefinition() {
283      return context.getWorker().fetchTypeDefinition(wrapped.fhirType());
284    }
285
286    @Override
287    public Base getBase() {
288      return wrapped;
289    }
290
291    @Override
292    public boolean hasNarrative() {
293      StructureDefinition sd = context.getWorker().fetchTypeDefinition(wrapped.fhirType());
294      while (sd != null) {
295        if ("DomainResource".equals(sd.getType())) {
296          return true;
297        }
298        sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
299      }
300      return false;
301
302    }
303
304    @Override
305    public String fhirType() {
306      return wrapped.fhirType();
307    }
308    
309    @Override
310    public PropertyWrapper getChildByName(String name) {
311      Property p = wrapped.getChildByName(name);
312      if (p == null)
313        return null;
314      else
315        return new PropertyWrapperDirect(context, p);
316    }
317
318    public Resource getResource() {
319      return wrapped;
320    }
321
322  }
323
324}