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