Merge pull request #918 from hapifhir/gg-202209-patient-rendering

Gg 202209 patient rendering
This commit is contained in:
Grahame Grieve 2022-09-08 23:53:14 +10:00 committed by GitHub
commit c14f9e74ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 673 additions and 51 deletions

View File

@ -4,4 +4,4 @@
## Other code changes
* no changes
* Rendering improvements for Patient and extension summary

View File

@ -81,7 +81,7 @@ public class BinaryRenderer {
String fn = "Binary-Native-"+bin.getId()+ext;
TextFile.bytesToFile(bin.getContent(), Utilities.path(folder, fn));
filenames.add(fn);
x.img("Binary-Native-"+bin.getId()+ext);
x.img("Binary-Native-"+bin.getId()+ext, "Binary");
}
}

View File

@ -383,10 +383,10 @@ public class LibraryRenderer extends ResourceRenderer {
p.code().tx(att.getContentType()+lang(att));
}
if (att.getData().length < LibraryRenderer.DATA_IMG_SIZE_CUTOFF) {
x.img("data: "+att.getContentType()+">;base64,"+b64(att.getData()));
x.img("data: "+att.getContentType()+">;base64,"+b64(att.getData()), "data");
} else {
String filename = "Library-"+baseId+(counter == 0 ? "" : "-"+Integer.toString(counter))+"."+imgExtension(att.getContentType());
x.img(filename);
x.img(filename, "data");
}
} else if (txt != null && !noShowData) {
XhtmlNode p = x.para();

View File

@ -124,9 +124,9 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
li.style("font-size: 11px");
if (useSelect) {
if (opt.getInitialSelected()) {
li.img("icon-selected.png");
li.img("icon-selected.png", "icon");
} else {
li.img("icon-not-selected.png");
li.img("icon-not-selected.png", "icon");
}
}
if (opt.getValue().isPrimitive()) {
@ -678,26 +678,26 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) {
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "Can change the subject of the questionnaire").img(Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "Can change the subject of the questionnaire").img(Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png"), "icon");
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden")) {
hasFlag = true;
flags.ah(Utilities.pathURL(context.getSpecificationLink(), "extension-questionnaire-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"));
flags.ah(Utilities.pathURL(context.getSpecificationLink(), "extension-questionnaire-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"), "icon");
d.style("background-color: #eeeeee");
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay")) {
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay", "Is optional to display").img(Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay", "Is optional to display").img(Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png"), "icon");
}
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod")) {
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", "Is linked to an observation").img(Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", "Is linked to an observation").img(Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png"), "icon");
}
if (i.hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory")) {
CodeableConcept cc = i.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory").getValueCodeableConcept();
String code = cc.getCode("http://hl7.org/fhir/questionnaire-display-category");
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-displayCategory", "Category: "+code).img(Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-displayCategory", "Category: "+code).img(Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"), "icon");
}
if (i.hasMaxLength()) {
@ -853,7 +853,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
boolean ext = false;
XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent");
td.an(q.getId());
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_root.gif"));
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_root.gif"), "icon");
td.tx(" Questionnaire ");
td.b().tx(q.getId());
@ -906,10 +906,10 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent");
td.an("item."+qi.getLinkId());
for (QuestionnaireItemComponent p : parents) {
td.ah("#item."+p.getLinkId()).img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"));
td.ah("#item."+p.getLinkId()).img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"), "icon");
td.tx(" > ");
}
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"));
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"), "icon");
td.tx(" Item ");
td.b().tx(qi.getLinkId());

View File

@ -3544,10 +3544,8 @@ public class ProfileUtilities extends TranslatingUtilities {
r1.getCells().add(gen.new Cell());
r1.getCells().add(gen.new Cell(null, null, describeCardinality(c, null, new UnusedTracker()), null, null));
genTypes(gen, r1, ved, defFile, ed, corePath, imagePath, false, false);
Cell cell = gen.new Cell();
cell.addMarkdown(c.getDefinition());
r1.getCells().add(cell);
r1.setIcon("icon_"+m+"extension_simple.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_SIMPLE);
generateDescription(gen, r1, c, null, true, corePath, corePath, ed, corePath, imagePath, false, false, false, ved, false, false, false, rc);
}
}
} else {
@ -4274,7 +4272,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// if (child.getPath().endsWith(".extension") || child.getPath().endsWith(".modifierExtension"))
// genElement(defPath, gen, row.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, true, false, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants);
}
if (typesRow != null) {
if (typesRow != null && !element.prohibited()) {
makeChoiceRows(typesRow.getSubRows(), element, gen, corePath, profileBaseFileName, mustSupport);
}
}
@ -4779,8 +4777,10 @@ public class ProfileUtilities extends TranslatingUtilities {
}
}
if (fixedUrl == null) {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "URL")+": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(ref, fullUrl, null));
if (!Utilities.noString(fullUrl)) {
c.getPieces().add(gen.new Piece(null, translate("sd.table", "URL")+": ", null).addStyle("font-weight:bold"));
c.getPieces().add(gen.new Piece(ref, fullUrl, null));
}
} else {
// reference to a profile take on the extension show the base URL
c.getPieces().add(gen.new Piece(null, translate("sd.table", "URL")+": ", null).addStyle("font-weight:bold"));

View File

@ -81,7 +81,7 @@ public class BinaryRenderer {
String fn = "Binary-Native-"+bin.getId()+ext;
TextFile.bytesToFile(bin.getContent(), Utilities.path(folder, fn));
filenames.add(fn);
x.img("Binary-Native-"+bin.getId()+ext);
x.img("Binary-Native-"+bin.getId()+ext, "binary");
}
}

View File

@ -679,6 +679,13 @@ public class DataRenderer extends Renderer {
renderSampledData(x, (SampledData) type);
} else if (type instanceof Reference) {
renderReference(x, (Reference) type);
} else if (type instanceof CodeableReference) {
CodeableReference cr = (CodeableReference) type;
if (cr.hasConcept()) {
renderCodeableConcept(x, cr.getConcept());
} else {
renderReference(x, cr.getReference());
}
} else if (type instanceof MarkdownType) {
addMarkdown(x, ((MarkdownType) type).asStringValue());
} else if (type.isPrimitive()) {

View File

@ -383,10 +383,10 @@ public class LibraryRenderer extends ResourceRenderer {
p.code().tx(att.getContentType()+lang(att));
}
if (att.getData().length < LibraryRenderer.DATA_IMG_SIZE_CUTOFF) {
x.img("data: "+att.getContentType()+">;base64,"+b64(att.getData()));
x.img("data: "+att.getContentType()+">;base64,"+b64(att.getData()), "data");
} else {
String filename = "Library-"+baseId+(counter == 0 ? "" : "-"+Integer.toString(counter))+"."+imgExtension(att.getContentType());
x.img(filename);
x.img(filename, "data");
}
} else if (txt != null && !noShowData) {
XhtmlNode p = x.para();

View File

@ -1,28 +1,76 @@
package org.hl7.fhir.r5.renderers;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.poi.hssf.record.chart.DatRecord;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Address;
import org.hl7.fhir.r5.model.Attachment;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.DateType;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.HumanName;
import org.hl7.fhir.r5.model.HumanName.NameUse;
import org.hl7.fhir.r5.model.Identifier;
import org.hl7.fhir.r5.model.Identifier.IdentifierUse;
import org.hl7.fhir.r5.model.Patient;
import org.hl7.fhir.r5.model.Period;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.renderers.PatientRenderer.NamedReferance;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class PatientRenderer extends ResourceRenderer {
public class NamedReferance {
private String name;
private Reference reference;
private BaseWrapper wrapper;
public NamedReferance(String name, Reference ref, BaseWrapper refw) {
this.name = name;
this.reference = ref;
this.wrapper = refw;
}
public String getName() {
return name;
}
public Reference getReference() {
return reference;
}
public BaseWrapper getWrapper() {
return wrapper;
}
}
private static final int MAX_IMAGE_LENGTH = 2*1024*1024;
public PatientRenderer(RenderingContext context) {
super(context);
}
@ -224,7 +272,542 @@ public class PatientRenderer extends ResourceRenderer {
@Override
public boolean render(XhtmlNode x, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
describe(x.para(), r);
// banner
describe(makeBanner(x.para()), r);
x.hr();
XhtmlNode tbl;
if (hasRenderablePhoto(r)) {
tbl = x.table("none");
XhtmlNode tr = tbl.tr();
tbl = tr.td().table("grid");
renderPhoto(tr.td(), r);
} else {
tbl = x.table("grid");
}
// the table has 4 columns
addStatus(tbl, r);
addIdentifiers(tbl, r);
addNames(tbl, r);
addComms(tbl, r);
addLangs(tbl, r);
addNOKs(tbl, r);
addLinks(tbl, r);
addExtensions(tbl, r);
if (tbl.isEmpty()) {
x.remove(tbl);
}
return false;
}
private void addExtensions(XhtmlNode tbl, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException {
Map<String, List<Extension>> extensions = new HashMap<>();
PropertyWrapper pw = getProperty(r, "extension");
for (BaseWrapper t : pw.getValues()) {
Extension ext = (Extension) t.getBase();
if (!extensions.containsKey(ext.getUrl())) {
extensions.put(ext.getUrl(), new ArrayList<>());
}
extensions.get(ext.getUrl()).add(ext);
}
for (String url : extensions.keySet()) {
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, url);
if (sd != null) {
List<Extension> list = extensions.get(url);
boolean anyComplex = false;
for (Extension ext : list) {
anyComplex = anyComplex || ext.hasExtension();
}
if (!anyComplex) {
XhtmlNode tr = tbl.tr();
nameCell(tr, sd.getTitle()+":", sd.getDescription(), sd.getUserString("path"));
XhtmlNode td = tr.td();
td.colspan("3");
if (list.size() == 1) {
XhtmlNode ul = td.ul();
for (Extension s : list) {
XhtmlNode li = ul.li();
render(r, li, s.getValue());
}
} else {
render(r, td, list.get(0).getValue());
}
} else {
for (Extension ext : list) {
XhtmlNode tr = tbl.tr();
nameCell(tr, sd.getTitle()+":", sd.getDescription());
XhtmlNode td = tr.td();
td.colspan("3");
if (ext.hasExtension()) {
XhtmlNode ul = td.ul();
for (Extension s : ext.getExtension()) {
XhtmlNode li = ul.li();
li.tx(s.getUrl()+": ");
if (s.hasExtension()) {
boolean first = true;
for (Extension t : s.getExtension()) {
if (first) first = false; else li.tx("; ");
li.tx(t.getUrl()+"=");
render(r, li, t.getValue());
}
} else {
render(r, li, s.getValue());
}
}
} else {
render(r, td, ext.getValue());
}
}
}
}
}
}
private void addIdentifiers(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
List<Identifier> ids = new ArrayList<>();
PropertyWrapper pw = getProperty(r, "identifier");
for (BaseWrapper t : pw.getValues()) {
ids.add((Identifier) t.getBase());
}
Identifier id = null;
for (Identifier i : ids) {
id = chooseId(id, i);
}
if (id != null) {
ids.remove(id);
};
if (ids.size() == 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Other Id:", "Other Ids (see the one above)");
XhtmlNode td = tr.td();
td.colspan("3");
render(r, td, ids.get(0));
} else if (ids.size() > 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Other Ids:", "Other Ids (see the one above)");
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
for (Identifier i : ids) {
render(r, ul.li(), i);
}
}
}
private void addLangs(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
List<CodeableConcept> langs = new ArrayList<>();
PropertyWrapper pw = getProperty(r, "communication");
CodeableConcept prefLang = null;
for (BaseWrapper t : pw.getValues()) {
PropertyWrapper l = getProperty(t, "language");
if (l != null && l.hasValues()) {
CodeableConcept lang = (CodeableConcept) l.getValues().get(0).getBase();
langs.add(lang);
l = getProperty(t, "preferred");
if (l != null && l.hasValues() && "true".equals(l.getValues().get(0).getBase().primitiveValue())) {
prefLang = lang;
}
}
}
if (langs.size() == 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Language:", "Languages spoken");
XhtmlNode td = tr.td();
td.colspan("3");
render(r, td, langs.get(0));
if (prefLang != null) {
td.tx(" (preferred)");
}
} else if (langs.size() > 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Languages:", "Languages spoken");
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
for (CodeableConcept i : langs) {
XhtmlNode li = ul.li();
render(r, li, i);
if (i == prefLang) {
li.tx(" (preferred)");
}
}
}
}
private void addLinks(XhtmlNode tbl, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException {
List<NamedReferance> refs = new ArrayList<>();
PropertyWrapper pw = getProperty(r, "generalPractitioner");
if (pw != null) {
for (BaseWrapper t : pw.getValues()) {
refs.add(new NamedReferance("General Practitioner", (Reference) t.getBase(), t));
}
}
pw = getProperty(r, "managingOrganization");
if (pw != null) {
for (BaseWrapper t : pw.getValues()) {
refs.add(new NamedReferance("Managing Organization", (Reference) t.getBase(), t));
}
}
pw = getProperty(r, "link");
for (BaseWrapper t : pw.getValues()) {
PropertyWrapper l = getProperty(t, "other");
Reference ref = null;
BaseWrapper refw = null;
for (BaseWrapper v : l.getValues()) {
ref = (Reference) v.getBase();
refw = v;
}
String type = null;
l = getProperty(t, "type");
for (BaseWrapper v : l.getValues()) {
type = v.getBase().primitiveValue();
}
if (type != null && ref != null) {
refs.add(new NamedReferance(describeLinkedRecord(type), ref, refw));
}
}
if (refs.size() > 0) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Links:", "Patient Links");
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
for (NamedReferance ref : refs) {
XhtmlNode li = ul.li();
li.tx(ref.getName());
li.tx(": ");
renderReference(r, li, ref.getReference());
}
}
}
private String describeLinkedRecord(String type) {
switch (type) {
case "replaced-by" : return "This record replaced by";
case "replaces": return "This record replaces";
case "refer": return "Please refer to";
case "seealso": return "Also see";
}
return "Unknown";
}
private void addNOKs(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
PropertyWrapper pw = getProperty(r, "contact");
for (BaseWrapper t : pw.getValues()) {
addNOK(tbl,r, t);
}
}
private void addNOK(XhtmlNode tbl, ResourceWrapper r, BaseWrapper bw) throws FHIRFormatError, DefinitionException, IOException {
List<CodeableConcept> rels = new ArrayList<>();
HumanName name = null;
Address add = null;
String gender = null;
Period period = null;
Reference organization = null;
List<ContactPoint> tels = new ArrayList<>();
PropertyWrapper pw = getProperty(bw, "relationship");
for (BaseWrapper t : pw.getValues()) {
CodeableConcept v = (CodeableConcept) t.getBase();
rels.add(v);
}
pw = getProperty(bw, "name");
if (pw.hasValues()) {
name = (HumanName) pw.getValues().get(0).getBase();
}
pw = getProperty(bw, "telecom");
for (BaseWrapper t : pw.getValues()) {
ContactPoint v = (ContactPoint) t.getBase();
tels.add(v);
}
pw = getProperty(bw, "address");
if (pw.hasValues()) {
add = (Address) pw.getValues().get(0).getBase();
}
pw = getProperty(bw, "gender");
if (pw.hasValues()) {
gender = pw.getValues().get(0).getBase().primitiveValue();
}
pw = getProperty(bw, "organization");
if (pw.hasValues()) {
organization = (Reference) pw.getValues().get(0).getBase();
}
pw = getProperty(bw, "period");
if (pw.hasValues()) {
period = (Period) pw.getValues().get(0).getBase();
}
if (rels.size() < 2 && name == null && add == null && gender == null && period == null && organization == null && tels.size() == 0) {
return; // nothing to render
}
XhtmlNode tr = tbl.tr();
if (rels.size() == 1) {
nameCell(tr, (rels.get(0).getCodingFirstRep().hasDisplay() ? rels.get(0).getCodingFirstRep().getDisplay() : display(rels.get(0)))+":", "Nominated Contact: "+display(rels.get(0)));
} else {
nameCell(tr, "Contact", "Patient contact");
}
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
XhtmlNode li;
if (name != null) {
li = ul.li();
render(r, li, name);
if (gender != null) {
li.tx(" ("+gender+")");
}
} else if (gender != null) {
li = ul.li();
li.tx("Gender: "+gender);
}
if (rels.size() > 1) {
li = ul.li();
li.tx("Relationships: ");
boolean first = true;
for (CodeableConcept rel : rels) {
if (first) first = false; else li.tx(", ");
render(r, li, rel);
}
}
if (add != null) {
render(r, ul.li(), add);
}
for (ContactPoint cp : tels) {
render(r, ul.li(), cp);
}
if (organization != null) {
li = ul.li();
li.tx("Organization: ");
render(r, li, organization);
}
if (period != null) {
li = ul.li();
li.tx("Valid Period: ");
render(r, li, period);
}
}
private void addNames(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
List<HumanName> names = new ArrayList<>();
PropertyWrapper pw = getProperty(r, "name");
for (BaseWrapper t : pw.getValues()) {
names.add((HumanName) t.getBase());
}
HumanName name = null;
for (HumanName n : names) {
name = chooseName(name, n);
}
if (name != null) {
names.remove(name);
};
if (names.size() == 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Alt. Name:", "Alternate names (see the one above)");
XhtmlNode td = tr.td();
td.colspan("3");
render(r, td, names.get(0));
} else if (names.size() > 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Alt Names:", "Alternate names (see the one above)");
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
for (HumanName n : names) {
render(r, ul.li(), n);
}
}
}
private void addComms(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, IOException {
List<ContactPoint> tels = new ArrayList<>();
PropertyWrapper pw = getProperty(r, "telecom");
for (BaseWrapper t : pw.getValues()) {
tels.add((ContactPoint) t.getBase());
}
List<Address> adds = new ArrayList<>();
pw = getProperty(r, "address");
for (BaseWrapper t : pw.getValues()) {
adds.add((Address) t.getBase());
}
if (tels.size() + adds.size() == 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Contact Detail:", "Ways to contact the Patient");
XhtmlNode td = tr.td();
td.colspan("3");
if (adds.isEmpty()) {
render(r, td, tels.get(0));
} else {
render(r, td, adds.get(0));
}
} else if (tels.size() + adds.size() > 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, "Contact Details:", "Ways to contact the Patient");
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
for (ContactPoint n : tels) {
render(r, ul.li(), n);
}
for (Address n : adds) {
render(r, ul.li(), n);
}
}
}
private void addStatus(XhtmlNode tbl, ResourceWrapper r) throws FHIRFormatError, DefinitionException, UnsupportedEncodingException, FHIRException, IOException {
// TODO Auto-generated method stub
int count = 0;
if (r.has("active")) {
count++;
}
if (r.has("deceased")) {
count++;
}
if (r.has("maritalStatus")) {
count++;
}
if (r.has("multipleBirth")) {
count++;
}
if (count > 0) {
XhtmlNode tr = tbl.tr();
int pos = 0;
if (r.has("active")) {
PropertyWrapper a = r.getChildByName("active");
if (a.hasValues()) {
pos++;
nameCell(tr, "Active:", "Record is active");
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
}
render(r, td, (DataType) a.value().getBase());
}
}
if (r.has("deceased[x]")) {
PropertyWrapper a = r.getChildByName("deceased[x]");
if (a.hasValues()) {
pos++;
nameCell(tr, "Deceased:", "Known status of Patient");
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
}
render(r, td, (DataType) a.value().getBase());
}
}
if (r.has("maritalStatus")) {
PropertyWrapper a = r.getChildByName("maritalStatus");
if (a.hasValues()) {
pos++;
if (pos == 3) {
tr = tbl.tr();
}
nameCell(tr, "Marital Status:", "Known Marital status of Patient");
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
}
render(r, td, (DataType) a.value().getBase());
}
}
if (r.has("multipleBirth[x]")) {
PropertyWrapper a = r.getChildByName("multipleBirth[x]");
if (a.hasValues()) {
pos++;
if (pos == 3) {
tr = tbl.tr();
}
nameCell(tr, "Multiple Birth:", "Known multipleBirth status of Patient");
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
}
render(r, td, (DataType) a.value().getBase());
}
}
}
}
private void nameCell(XhtmlNode tr, String text, String title) {
XhtmlNode td = tr.td();
td.setAttribute("title", title);
td.tx(text);
td.style("background-color: #f3f5da");
}
private void nameCell(XhtmlNode tr, String text, String title, String link) {
XhtmlNode td = tr.td();
td.setAttribute("title", title);
if (link != null) {
td.ah(link).tx(text);
} else {
td.tx(text);
}
td.style("background-color: #f3f5da");
}
private void renderPhoto(XhtmlNode td, ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException {
if (r.has("photo")) {
PropertyWrapper a = r.getChildByName("photo");
for (BaseWrapper v : a.getValues()) {
Attachment att = (Attachment) v.getBase();
if (att.getContentType().startsWith("image/") &&
att.getData() != null && (!context.isInlineGraphics() || (att.getData().length > 0 && att.getData().length < MAX_IMAGE_LENGTH))) {
String ext = extensionForType(att.getContentType());
if (context.isInlineGraphics() || Utilities.noString(context.getDestDir()) || ext == null) {
td.img("data:"+att.getContentType()+";base64,"+att.getDataElement().asStringValue(), "patient photo");
} else {
String n = UUID.randomUUID().toString().toLowerCase()+ext;
TextFile.bytesToFile(att.getData(), new File(Utilities.path(context.getDestDir(), n)));
td.img(n, "patient photo");
}
return;
}
}
}
return;
}
private String extensionForType(String contentType) {
if (contentType.equals("image/gif")) {
return ".gif";
}
if (contentType.equals("image/png")) {
return ".png";
}
if (contentType.equals("image/jpeg")) {
return ".jpg";
}
return null;
}
private boolean hasRenderablePhoto(ResourceWrapper r) throws UnsupportedEncodingException, FHIRException, IOException {
if (r.has("photo")) {
PropertyWrapper a = r.getChildByName("photo");
for (BaseWrapper v : a.getValues()) {
Attachment att = (Attachment) v.getBase();
if (att.getContentType().startsWith("image/") &&
att.getData() != null && (!context.isInlineGraphics() || (att.getData().length > 0 && att.getData().length < MAX_IMAGE_LENGTH))) {
return true;
}
}
}
return false;
}
private XhtmlNode makeBanner(XhtmlNode para) {
para.style("border: 1px #661aff solid; background-color: #e6e6ff; padding: 10px;");
return para;
}
}

View File

@ -124,9 +124,9 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
li.style("font-size: 11px");
if (useSelect) {
if (opt.getInitialSelected()) {
li.img("icon-selected.png");
li.img("icon-selected.png", "icon");
} else {
li.img("icon-not-selected.png");
li.img("icon-not-selected.png", "icon");
}
}
if (opt.getValue().isPrimitive()) {
@ -244,28 +244,28 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
Cell flags = gen.new Cell();
r.getCells().add(flags);
if (i.getReadOnly()) {
flags.addPiece(gen.new Piece(Utilities.pathURL(context.getSpecificationLink(), "questionnaire-definitions.html#Questionnaire.item.readOnly"), null, "Is Readonly").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-readonly.png"))));
flags.addPiece(gen.new Piece(Utilities.pathURL(context.getSpecificationLink(), "questionnaire-definitions.html#Questionnaire.item.readOnly"), null, "Is Readonly").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-readonly.png"))));
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) {
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-isSubject.html"), null, "Can change the subject of the questionnaire").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png"))));
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-isSubject.html"), null, "Can change the subject of the questionnaire").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png"))));
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden")) {
flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-hidden.html"), null, "Is a hidden item").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"))));
flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-hidden.html"), null, "Is a hidden item").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"))));
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay")) {
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-optionalDisplay.html"), null, "Is optional to display").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png"))));
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-optionalDisplay.html"), null, "Is optional to display").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png"))));
}
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod")) {
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-observationLinkPeriod"), null, "Is linked to an observation").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png"))));
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-observationLinkPeriod"), null, "Is linked to an observation").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png"))));
}
if (i.hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation")) {
String code = ToolingExtensions.readStringExtension(i, "http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation");
flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-choiceorientation.html"), null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-choiceorientation.html"), null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
}
if (i.hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory")) {
CodeableConcept cc = i.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory").getValueCodeableConcept();
String code = cc.getCode("http://hl7.org/fhir/questionnaire-display-category");
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-displayCategory"), null, "Category: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
flags.addPiece(gen.new Piece(getSDCLink("StructureDefinition-sdc-questionnaire-displayCategory"), null, "Category: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
}
}
Cell defn = gen.new Cell();
@ -668,7 +668,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
// if (i.hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation")) {
// String code = ToolingExtensions.readStringExtension(i, "http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation");
// flags.addPiece(gen.new Piece("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
// flags.addPiece(gen.new Piece("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
//}
@ -679,26 +679,26 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject")) {
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "Can change the subject of the questionnaire").img(Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-isSubject", "Can change the subject of the questionnaire").img(Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png"), "icon");
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden")) {
hasFlag = true;
flags.ah(Utilities.pathURL(context.getSpecificationLink(), "extension-questionnaire-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"));
flags.ah(Utilities.pathURL(context.getSpecificationLink(), "extension-questionnaire-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png"), "icon");
d.style("background-color: #eeeeee");
}
if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay")) {
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay", "Is optional to display").img(Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-optionalDisplay", "Is optional to display").img(Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png"), "icon");
}
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod")) {
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", "Is linked to an observation").img(Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-observationLinkPeriod", "Is linked to an observation").img(Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png"), "icon");
}
if (i.hasExtension("http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory")) {
CodeableConcept cc = i.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/questionnaire-displayCategory").getValueCodeableConcept();
String code = cc.getCode("http://hl7.org/fhir/questionnaire-display-category");
hasFlag = true;
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-displayCategory", "Category: "+code).img(Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"));
flags.ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-displayCategory", "Category: "+code).img(Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"), "icon");
}
if (i.hasMaxLength()) {
@ -854,7 +854,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
boolean ext = false;
XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent");
td.an(q.getId());
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_root.gif"));
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_root.gif"), "icon");
td.tx(" Questionnaire ");
td.b().tx(q.getId());
@ -907,10 +907,10 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent");
td.an("item."+qi.getLinkId());
for (QuestionnaireItemComponent p : parents) {
td.ah("#item."+p.getLinkId()).img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"));
td.ah("#item."+p.getLinkId()).img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"), "icon");
td.tx(" > ");
}
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"));
td.img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png"), "icon");
td.tx(" Item ");
td.b().tx(qi.getLinkId());

View File

@ -431,7 +431,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
//
//// if (i.hasExtension("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-choiceOrientation")) {
//// String code = ToolingExtensions.readStringExtension(i, "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-choiceOrientation");
//// flags.addPiece(gen.new Piece("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod", null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
//// flags.addPiece(gen.new Piece("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod", null, "Orientation: "+code).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png"))));
////}
//
//

View File

@ -11,7 +11,9 @@ import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.CodeableReference;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem;
@ -172,6 +174,36 @@ public abstract class ResourceRenderer extends DataRenderer {
}
}
public void render(Resource res, XhtmlNode x, DataType type) throws FHIRFormatError, DefinitionException, IOException {
if (type instanceof Reference) {
renderReference(res, x, (Reference) type);
} else if (type instanceof CodeableReference) {
CodeableReference cr = (CodeableReference) type;
if (cr.hasReference()) {
renderReference(res, x, cr.getReference());
} else {
render(x, type);
}
} else {
render(x, type);
}
}
public void render(ResourceWrapper res, XhtmlNode x, DataType type) throws FHIRFormatError, DefinitionException, IOException {
if (type instanceof Reference) {
renderReference(res, x, (Reference) type);
} else if (type instanceof CodeableReference) {
CodeableReference cr = (CodeableReference) type;
if (cr.hasReference()) {
renderReference(res, x, cr.getReference());
} else {
render(x, type);
}
} else {
render(x, type);
}
}
public void renderReference(Resource res, XhtmlNode x, Reference r) throws UnsupportedEncodingException, IOException {
ResourceWrapper rw = new ResourceWrapperDirect(this.context, res);
renderReference(rw, x, r);

View File

@ -323,7 +323,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
protected void clipboard(XhtmlNode x, String img, String title, String source) {
XhtmlNode span = x.span("cursor: pointer", "Copy "+title+" Format to clipboard");
span.attribute("onClick", "navigator.clipboard.writeText('"+Utilities.escapeJson(source)+"');");
span.img(img).setAttribute("width", "24px").setAttribute("height", "16px");
span.img(img, "btn").setAttribute("width", "24px").setAttribute("height", "16px");
}

View File

@ -120,9 +120,9 @@ public class CDARoundTripTests {
//
// assertEquals("Skin Exam", fp.evaluateToString(e, "component.structuredBody.component.section.component.section.where(code.code='8709-8' and code.codeSystem='2.16.840.1.113883.6.1').title.dataString"));
// // <div>Erythematous rash, palmar surface, left index finger.
// // <img src="MM1"/></div>
// // <img src="MM1" alt=\"img\"/></div>
// String text = fp.evaluateToString(e, "component.structuredBody.component.section.component.section.where(code.code='8709-8' and code.codeSystem='2.16.840.1.113883.6.1').text");
// assertTrue(text.contains("<img src=\"MM1\"/>"));
// assertTrue(text.contains("<img src=\"MM1\" alt=\"img\"/>"));
// } catch (Exception e) {
// System.out.println(e.getMessage());
// e.printStackTrace();

View File

@ -815,7 +815,7 @@ public class HierarchicalTableGenerator extends TranslatingUtilities {
else
tc.setAttribute("style", "vertical-align: top; text-align : left; "+(c.cellStyle != null && c.cellStyle.contains("background-color") ? "" : "background-color: "+color+"; ")+"border: "+ border +"px #F0F0F0 solid; padding:0px 4px 0px 4px"+(c.cellStyle != null ? ";"+c.cellStyle : ""));
if (!Utilities.noString(icon)) {
XhtmlNode img = tc.addTag("img").setAttribute("src", srcFor(imagePath, icon)).setAttribute("class", "hierarchy").setAttribute("style", "background-color: "+color+"; background-color: inherit").setAttribute("alt", ".");
XhtmlNode img = tc.addTag("img").setAttribute("alt", "icon").setAttribute("src", srcFor(imagePath, icon)).setAttribute("class", "hierarchy").setAttribute("style", "background-color: "+color+"; background-color: inherit").setAttribute("alt", ".");
if (hint != null)
img.setAttribute("title", hint);
tc.addText(" ");

View File

@ -656,12 +656,12 @@ public class XhtmlNode implements IBaseXhtml {
return addTag("a").attribute("href", href).attribute("title", title);
}
public XhtmlNode img(String src) {
return addTag("img").attribute("src", src);
public XhtmlNode img(String src, String alt) {
return addTag("img").attribute("src", src).attribute("alt", alt);
}
public XhtmlNode img(String src, String title) {
return addTag("img").attribute("src", src).attribute("title", title);
public XhtmlNode img(String src, String alt, String title) {
return addTag("img").attribute("src", src).attribute("alt", alt).attribute("title", title);
}
public XhtmlNode an(String href) {