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