001package org.hl7.fhir.r4b.renderers;
002
003import java.io.IOException;
004import java.io.UnsupportedEncodingException;
005
006import org.apache.poi.hssf.record.chart.DatRecord;
007import org.hl7.fhir.r4b.model.DateTimeType;
008import org.hl7.fhir.r4b.model.DateType;
009import org.hl7.fhir.r4b.model.DomainResource;
010import org.hl7.fhir.r4b.model.HumanName;
011import org.hl7.fhir.r4b.model.HumanName.NameUse;
012import org.hl7.fhir.r4b.model.Identifier;
013import org.hl7.fhir.r4b.model.Identifier.IdentifierUse;
014import org.hl7.fhir.r4b.model.Patient;
015import org.hl7.fhir.r4b.model.Resource;
016import org.hl7.fhir.r4b.renderers.utils.RenderingContext;
017import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.BaseWrapper;
018import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.PropertyWrapper;
019import org.hl7.fhir.r4b.renderers.utils.BaseWrappers.ResourceWrapper;
020import org.hl7.fhir.utilities.xhtml.XhtmlNode;
021
022public class PatientRenderer extends ResourceRenderer {
023
024  public PatientRenderer(RenderingContext context) {
025    super(context);
026  }
027
028  public boolean render(XhtmlNode x, Resource dr) throws UnsupportedEncodingException, IOException {
029    describe(x, dr);
030    return false;
031  }
032
033  // name gender DoB (MRN)
034  public String display(Resource dr) {
035    Patient pat = (Patient) dr;
036    Identifier id = null;
037    for (Identifier t : pat.getIdentifier()) {
038      id = chooseId(id, t);
039    }
040    HumanName n = null;
041    for (HumanName t : pat.getName()) {
042      n = chooseName(n, t);
043    }
044    return display(n, pat.getGender().getDisplay(), pat.getBirthDateElement(), id);
045  }
046
047  private Identifier chooseId(Identifier oldId, Identifier newId) {
048    if (oldId == null) {
049      return newId;
050    }
051    if (newId == null) {
052      return oldId;
053    }
054    return isPreferred(newId.getUse(), oldId.getUse()) ? newId : oldId;
055  }
056
057  private boolean isPreferred(IdentifierUse newUse, IdentifierUse oldUse) {
058    if (newUse == null && oldUse == null || newUse == oldUse) {
059      return false;
060    }
061    if (newUse == null) {
062      return true;
063    }
064    switch (newUse) {
065    case NULL: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.USUAL);
066    case OFFICIAL: return !existsInList(oldUse, IdentifierUse.USUAL);
067    case OLD: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.SECONDARY, IdentifierUse.USUAL);
068    case SECONDARY: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.USUAL);
069    case TEMP: return !existsInList(oldUse, IdentifierUse.OFFICIAL, IdentifierUse.SECONDARY, IdentifierUse.USUAL);
070    case USUAL: return true;
071    default: return false;
072    }
073  }
074
075  private boolean existsInList(IdentifierUse oldUse, IdentifierUse... values) {
076    for (IdentifierUse value : values) {
077      if (value == oldUse) {
078        return true;
079      }
080    }
081    return false;
082  }
083
084  private HumanName chooseName(HumanName oldName, HumanName newName) {
085    if (oldName == null) {
086      return newName;
087    }
088    if (newName == null) {
089      return oldName;
090    }
091    return isPreferred(newName.getUse(), oldName.getUse()) ? newName : oldName;
092  }
093
094
095  private boolean isPreferred(NameUse newUse, NameUse oldUse) {
096    if (newUse == null && oldUse == null || newUse == oldUse) {
097      return false;
098    }
099    if (newUse == null) {
100      return true;
101    }
102    switch (oldUse) {
103      case ANONYMOUS: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
104      case MAIDEN: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
105      case NICKNAME: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
106      case NULL: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
107      case OFFICIAL: return existsInList(newUse, NameUse.USUAL);
108      case OLD: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
109      case TEMP: return existsInList(newUse, NameUse.OFFICIAL, NameUse.USUAL);
110      case USUAL: return false; 
111    }
112    return false;
113  }
114
115  private boolean existsInList(NameUse oldUse, NameUse... values) {
116    for (NameUse value : values) {
117      if (value == oldUse) {
118        return true;
119      }
120    }
121    return false;
122  }
123
124  @Override
125  public String display(ResourceWrapper pat) throws UnsupportedEncodingException, IOException {
126    Identifier id = null;
127    PropertyWrapper pw = getProperty(pat, "identifier");
128    for (BaseWrapper t : pw.getValues()) {
129      id = chooseId(id, (Identifier) t.getBase());
130    }
131    pw = getProperty(pat, "name");
132    HumanName n = null;
133    for (BaseWrapper t : pw.getValues()) {
134      n = chooseName(n, (HumanName) t);
135    }
136    String gender = null;
137    pw = getProperty(pat, "gender");
138    if (valued(pw)) {
139      pw.value().getBase().primitiveValue();
140    }
141    DateType dt = null; 
142    pw = getProperty(pat, "birthDate");
143    if (valued(pw)) {
144      dt = (DateType) pw.value().getBase();
145    }
146    return display(n, gender, dt, id);  
147  }
148
149  public void describe(XhtmlNode x, ResourceWrapper pat) throws UnsupportedEncodingException, IOException {
150    Identifier id = null;
151    PropertyWrapper pw = getProperty(pat, "identifier");
152    for (BaseWrapper t : pw.getValues()) {
153      id = chooseId(id, (Identifier) t.getBase());
154    }
155    pw = getProperty(pat, "name");
156    HumanName n = null;
157    for (BaseWrapper t : pw.getValues()) {
158      n = chooseName(n, (HumanName) t.getBase());
159    }
160    String gender = null;
161    pw = getProperty(pat, "gender");
162    if (valued(pw)) {
163      pw.value().getBase().primitiveValue();
164    }
165    DateType dt = null; 
166    pw = getProperty(pat, "birthDate");
167    if (valued(pw)) {
168      dt = (DateType) pw.value().getBase();
169    }
170    describe(x, n, gender, dt, id);
171  }
172
173
174  private String display(HumanName name, String gender, DateType dob, Identifier id) {
175    StringBuilder b = new StringBuilder();
176    b.append(display(name));
177    b.append(" ");
178    if (dob == null) {
179      b.append("??");
180    } else {
181      b.append(gender);
182    }
183    b.append(" ");
184    if (dob == null) {
185      b.append("DoB Unknown");
186    } else {
187      b.append(display(dob));      
188    }
189    if (id != null) {
190      b.append(" ( ");      
191      b.append(display(id));
192      b.append(")");      
193    }
194    return b.toString();
195  }
196  
197  public void describe(XhtmlNode x, HumanName name, String gender, DateType dob, Identifier id) throws UnsupportedEncodingException, IOException {
198    if (name == null) {
199      x.b().tx("Unnamed Patient"); // todo: is this appropriate?  
200    } else {
201      render(x.b(), name);
202    }
203    x.tx(" ");
204    if (gender == null) {
205      x.tx("??");
206    } else {
207      x.tx(gender);
208    }
209    x.tx(" ");
210    if (dob == null) {
211      x.tx("DoB Unknown");
212    } else {
213      render(x, dob);
214    }
215    if (id != null) {
216      x.tx(" ( ");      
217      render(x, id);
218      x.tx(")");      
219    }
220  }
221
222
223}