org.hl7.fhir.r5.renderers.QuestionnaireRenderer Maven / Gradle / Ivy
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nonnull;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.r5.renderers.utils.ResourceWrapper;
import org.hl7.fhir.r5.terminologies.expansion.ValueSetExpansionOutcome;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@MarkedToMoveToAdjunctPackage
public class QuestionnaireRenderer extends TerminologyRenderer {
public QuestionnaireRenderer(RenderingContext context) {
super(context);
}
@Override
public String buildSummary(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return canonicalTitle(r);
}
@Override
public void buildNarrative(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
renderResourceTechDetails(q, x);
genSummaryTable(status, x, (CanonicalResource) q.getResourceNative());
switch (context.getQuestionnaireMode()) {
case FORM:
renderForm(status, x, q);
break;
case LINKS:
renderLinks(status, x, q);
break;
case LOGIC:
renderLogic(status, x, q);
break;
case DEFNS:
renderDefns(status, x, q);
break;
case TREE:
renderTree(status, x, q);
break;
default:
throw new Error("Unknown questionnaire Renderer Mode");
}
boolean first = true;
for (ResourceWrapper cont : q.children("contained")) {
if (first) {
x.h2().tx("Contained Resources");
first = false;
}
x.hr();
RendererFactory.factory(cont, context.forContained()).setInner(true).buildNarrative(status, x, cont);
}
}
public void renderTree(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws UnsupportedEncodingException, IOException {
boolean hasFlags = checkForFlags(q.children("item"));
boolean doOpts = context.getDefinitionsTarget() == null && hasAnyOptions(q.children("item"));
if (doOpts) {
x.b().tx(context.formatPhrase(RenderingContext.QUEST_STRUCT));
}
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, "");
TableModel model = gen.new TableModel("qtree="+q.getId(), context.getRules() == GenerationRules.IG_PUBLISHER);
model.setAlternating(true);
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.QUEST_LINKID)), (context.formatPhrase(RenderingContext.QUEST_LINK)), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.QUEST_TEXT)), (context.formatPhrase(RenderingContext.QUEST_TEXTFOR)), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.GENERAL_CARDINALITY)), (context.formatPhrase(RenderingContext.QUEST_TIMES)), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.GENERAL_TYPE)), (context.formatPhrase(RenderingContext.QUEST_TYPE_ITEM)), null, 0));
if (hasFlags) {
model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.GENERAL_FLAGS)), (context.formatPhrase(RenderingContext.QUEST_ATTRIBUTES)), null, 0));
}
model.getTitles().add(gen.new Title(null, model.getDocoRef(), (context.formatPhrase(RenderingContext.GENERAL_DESC_CONST)), (context.formatPhrase(RenderingContext.QUEST_ADD_INFO)), null, 0));
// first we add a root for the questionaire itself
Row row = addTreeRoot(gen, model.getRows(), q, hasFlags);
for (ResourceWrapper i : q.children("item")) {
renderTreeItem(status, gen, row.getSubRows(), q, i, hasFlags);
}
XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null);
x.addChildNode(xn);
if (doOpts) {
renderOptions(q, x);
}
}
private void renderOptions(ResourceWrapper q, XhtmlNode x) {
if (hasAnyOptions(q.children("item"))) {
x.hr();
x.para().b().tx(context.formatPhrase(RenderingContext.QUEST_OPT));
renderOptions(q.children("item"), x);
}
}
private void renderOptions(List items, XhtmlNode x) {
for (ResourceWrapper i : items) {
renderItemOptionsList(x, i);
renderOptions(i.children("item"), x);
}
}
public void renderItemOptions(XhtmlNode x, ResourceWrapper i) {
if (i.has("answerOption")) {
for (ResourceWrapper opt : i.children("answerOption")) {
String value = "??";
String text = "??";
ResourceWrapper v = opt.child("value");
if (v.isPrimitive()) {
value = v.primitiveValue();
text = v.primitiveValue();
} else if (v.fhirType().equals("Coding")) {
if (v.has("system")) {
value = v.primitiveValue("system")+"#"+v.primitiveValue("code");
} else {
value = v.primitiveValue("code");
}
if (v.has("display")) {
text = v.primitiveValue("display");
} else {
text = v.primitiveValue("code");
}
}
if (value == null) {
value = "??";
}
if (text == null) {
text = "??";
}
boolean selected = "true".equals(opt.primitiveValue("initialSelected"));
x.option(value, text, selected);
}
}
}
public void renderItemOptionsList(XhtmlNode x, ResourceWrapper i) {
if (i.has("answerOption")) {
x.an(context.prefixAnchor("opt-item."+i.primitiveValue("linkId")));
x.para().b().tx(context.formatPhrase(RenderingContext.QUEST_ANSW, i.primitiveValue("linkId"))+" ");
XhtmlNode ul = x.ul();
for (ResourceWrapper opt : i.children("answerOption")) {
XhtmlNode li = ul.li();
li.style("font-size: 11px");
ResourceWrapper v = opt.child("value");
if (v.isPrimitive()) {
li.tx(v.primitiveValue());
} else if (v.fhirType().equals("Coding")) {
String link = v.has("system") ? new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), v.primitiveValue("system")) : null;
if (link == null) {
li.tx(v.primitiveValue("system")+"#"+v.primitiveValue("code"));
} else {
li.ah(link).tx(displaySystem(v.primitiveValue("system")));
li.tx(": "+v.primitiveValue("code"));
}
if (v.has("display")) {
li.tx(" (\""+v.primitiveValue("display")+"\")");
}
} else {
li.tx("??");
}
}
}
}
private boolean hasAnyOptions(List items) {
for (ResourceWrapper i : items) {
if (i.has("answerOption")) {
return true;
}
if (hasAnyOptions(i.children("item"))) {
return true;
}
}
return false;
}
private boolean checkForFlags(List items) {
for (ResourceWrapper i : items) {
if (checkForFlags(i)) {
return true;
}
}
return false;
}
private boolean checkForFlags(ResourceWrapper i) {
if (i.has("readOnly")) {
return true;
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_IS_SUBJ))) {
return true;
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) {
return true;
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) {
return true;
}
if (i.hasExtension(ToolingExtensions.EXT_O_LINK_PERIOD)) {
return true;
}
if (i.hasExtension(ToolingExtensions.EXT_Q_CHOICE_ORIENT)) {
return true;
}
if (i.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) {
return true;
}
return checkForFlags(i.children("item"));
}
private Row addTreeRoot(HierarchicalTableGenerator gen, List rows, ResourceWrapper q, boolean hasFlags) throws IOException {
Row r = gen.new Row();
rows.add(r);
r.setIcon("icon_q_root.gif", context.formatPhrase(RenderingContext.QUEST_ROOT));
r.getCells().add(gen.new Cell(null, null, q.primitiveValue("name"), null, null));
r.getCells().add(gen.new Cell(null, null, q.primitiveValue("description"), null, null));
r.getCells().add(gen.new Cell(null, null, "", null, null));
r.getCells().add(gen.new Cell(null, null, context.formatPhrase(RenderingContext.QUEST_QUEST), null, null));
if (hasFlags) {
r.getCells().add(gen.new Cell(null, null, "", null, null));
}
r.getCells().add(gen.new Cell(null, null, q.has("url") ? q.has("version") ? q.primitiveValue("url")+"#"+q.primitiveValue("version") : q.primitiveValue("url") : "", null, null));
return r;
}
private String getSpecLink(String path) {
return Utilities.pathURL(context.getLink(KnownLinkType.SPEC), path);
}
private String getSDCLink(String url, String path) {
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, url);
if (sd == null) {
sd = context.getContext().fetchResource(StructureDefinition.class, path);
}
if (sd != null && sd.hasWebPath()) {
return sd.getWebPath();
} else if (Utilities.isAbsoluteUrl(path)) {
return path.replace("StructureDefinition/", "StructureDefinition-")+".html";
} else if ("http://hl7.org/fhir/uv/sdc".equals(context.getPkp().getCanonicalForDefaultContext())) {
return Utilities.pathURL(path); // for now?
} else {
return Utilities.pathURL("http://hl7.org/fhir/uv/sdc", path); // for now?
}
}
private void renderTreeItem(RenderingStatus status, HierarchicalTableGenerator gen, List rows, ResourceWrapper q, ResourceWrapper i, boolean hasFlags) throws IOException {
Row r = gen.new Row();
rows.add(r);
String type = i.primitiveValue("type");
r.setIcon("icon-q-"+type.toLowerCase()+".png", type);
Cell c1 = gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), i.primitiveValue("linkId"), null, null);
c1.setId("item."+i.primitiveValue("linkId"));
r.getCells().add(c1);
String txt = (i.has("prefix") ? i.primitiveValue("prefix") + ". " : "") + i.primitiveValue("text");
r.getCells().add(gen.new Cell(null, null, txt, null, null));
r.getCells().add(gen.new Cell(null, null, ("true".equals(i.primitiveValue("required")) ? "1" : "0")+".."+("true".equals(i.primitiveValue("repeats")) ? "*" : "1"), null, null));
if (i.child("type").hasExtension(ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL)) {
status.setExtensions(true);
String t = i.child("type").extensionString(ToolingExtensions.EXT_QUESTIONNAIRE_ITEM_TYPE_ORIGINAL);
r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+t, t, null, null));
} else {
r.getCells().add(gen.new Cell(null, context.getLink(KnownLinkType.SPEC)+"codesystem-item-type.html#item-type-"+type, type, null, null));
}
if (hasFlags) {
// flags:
Cell flags = gen.new Cell();
r.getCells().add(flags);
if ("true".equals(i.primitiveValue("readOnly"))) {
flags.addPiece(gen.new Piece(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "questionnaire-definitions.html#Questionnaire.item.readOnly"), null, context.formatPhrase(RenderingContext.QUEST_READONLY)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-readonly.png"))));
}
if ("true".equals(i.extensionString("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject"))) {
status.setExtensions(true);
flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject", "StructureDefinition-sdc-questionnaire-isSubject.html"), null, context.formatPhrase(RenderingContext.QUEST_SUBJECT)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-subject.png"))));
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) {
status.setExtensions(true);
flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-hidden.html"), null, context.formatPhrase(RenderingContext.QUEST_HIDDEN)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-hidden.png"))));
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) {
status.setExtensions(true);
flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-optionalDisplay", "StructureDefinition-sdc-questionnaire-optionalDisplay.html"), null, context.formatPhrase(RenderingContext.QUEST_DISPLAY)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-optional.png"))));
}
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod")) {
status.setExtensions(true);
flags.addPiece(gen.new Piece(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod", "StructureDefinition-sdc-questionnaire-observationLinkPeriod.html"), null, context.formatPhrase(RenderingContext.QUEST_LINKED)).addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-observation.png"))));
}
if (i.hasExtension(ToolingExtensions.EXT_Q_CHOICE_ORIENT)) {
status.setExtensions(true);
String code = i.extensionString(ToolingExtensions.EXT_Q_CHOICE_ORIENT);
flags.addPiece(gen.new Piece(getSpecLink("extension-questionnaire-choiceorientation.html"), null, context.formatPhrase(RenderingContext.QUEST_ORIENTATION, code)+" ").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-" + code + ".png"))));
}
if (i.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) {
status.setExtensions(true);
ResourceWrapper cc = i.extensionValue(ToolingExtensions.EXT_Q_DISPLAY_CAT);
String code = getCodeFromCC(cc, "http://hl7.org/fhir/questionnaire-display-category");
flags.addPiece(gen.new Piece("https://hl7.org/fhir/R4/extension-questionnaire-displayCategory.html", null, context.formatPhrase(RenderingContext.QUEST_CAT, code)+" ").addHtml(new XhtmlNode(NodeType.Element, "img").attribute("alt", "icon").attribute("src", getImgPath("icon-qi-" + code + ".png"))));
}
}
Cell defn = gen.new Cell();
r.getCells().add(defn);
if (i.has("maxLength")) {
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH)+" "), null));
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("maxLength"), null));
}
if (i.has("definition")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_DEFINITION_COLON)+" "), null));
genDefinitionLink(gen, i, defn, q);
}
if (i.has("enableWhen")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
Piece p = gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_ENABLE)+" "), null);
defn.getPieces().add(p);
if (i.children("enableWhen").size() == 1) {
XhtmlNode x = new XhtmlNode(NodeType.Element, "span");
p.getChildren().add(x);
renderEnableWhen(x, i.firstChild("enableWhen"));
} else {
XhtmlNode x = new XhtmlNode(NodeType.Element, "ul");
p.getChildren().add(x);
for (ResourceWrapper qi : i.children("enableWhen")) {
renderEnableWhen(x.li(), qi);
}
}
}
if (i.has("answerValueSet")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_VALUE)+" "), null));
if (i.hasPrimitiveValue("answerValueSet") && i.primitiveValue("answerValueSet").startsWith("#")) {
ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1));
if (vs == null) {
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null));
} else {
defn.getPieces().add(gen.new Piece(vs.getWebPath(), RendererFactory.factory(vs, context.forContained()).buildSummary(vs), null));
}
} else {
ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"));
if (vs == null || !vs.hasWebPath()) {
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null));
} else {
defn.getPieces().add(gen.new Piece(vs.getWebPath(), vs.present(), null));
}
}
}
if (i.has("answerOption")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_OPTIONS)+" "), null));
if (context.getDefinitionsTarget() == null) {
// if we don't have a definitions target, we'll add them below.
defn.getPieces().add(gen.new Piece("#"+context.prefixAnchor("opt-item."+i.primitiveValue("linkId")), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), null));
} else {
defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), null));
}
}
if (i.has("initial")) {
for (ResourceWrapper v : i.children("initial")) {
ResourceWrapper vv = v.child("value");
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_INITIAL)+" "), null));
defn.getPieces().add(gen.new Piece(null, vv.fhirType(), null));
defn.getPieces().add(gen.new Piece(null, " = ", null));
if (vv.isPrimitive()) {
defn.getPieces().add(gen.new Piece(null, vv.primitiveValue(), null));
} else if (vv.fhirType().equals("Coding")) {
renderCoding(gen, defn.getPieces(), vv);
} else if (vv.fhirType().equals("Quantity")) {
renderQuantity(gen, defn.getPieces(), vv, false);
} else if (vv.fhirType().equals("Reference")) {
renderReference(q, gen, defn.getPieces(), vv, true);
} else if (vv.fhirType().equals("Attachment")) {
// renderAttachment(gen, defn.getPieces(), vv);
}
}
}
// still todo
//
//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-choiceColumn
//
//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-width
//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod
//http://hl7.org/fhir/StructureDefinition/Questionnaire-itemControl
//http://hl7.org/fhir/StructureDefinition/Questionnaire-sliderStepValue
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_EXP)+" "), null));
Piece p = gen.new Piece("ul");
defn.getPieces().add(p);
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_INT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_ITEM_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_EN), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CALC), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CAND), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression");
}
}
for (ResourceWrapper c : i.children("item")) {
renderTreeItem(status, gen, r.getSubRows(), q, c, hasFlags);
}
}
private String getCodeFromCC(ResourceWrapper cc, String system) {
for (ResourceWrapper coding : cc.children("coding")) {
if (system.equals(coding.primitiveValue("system"))) {
return coding.primitiveValue("code");
}
}
return null;
}
public void genDefinitionLink(HierarchicalTableGenerator gen, ResourceWrapper i, Cell defn, ResourceWrapper q) {
// can we resolve the definition?
String path = null;
String d = i.primitiveValue("definition");
if (d.contains("#")) {
path = d.substring(d.indexOf("#")+1);
d = d.substring(0, d.indexOf("#"));
}
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q.getResourceNative());
if (sd != null) {
String url = sd.getWebPath();
if (url != null) {
defn.getPieces().add(gen.new Piece(url+"#"+path, path, null));
} else {
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("definition"), null));
}
} else {
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("definition"), null));
}
}
public void genDefinitionLink(XhtmlNode x, ResourceWrapper i, ResourceWrapper q) {
// can we resolve the definition?
String path = null;
String d = i.primitiveValue("definition");
if (d.contains("#")) {
path = d.substring(d.indexOf("#")+1);
d = d.substring(0, d.indexOf("#"));
}
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q.getResourceNative());
if (sd != null) {
String url = sd.getWebPath();
if (url != null) {
x.ah(url+"#"+path).tx(path);
} else {
x.tx(i.primitiveValue("definition"));
}
} else {
x.tx(i.primitiveValue("definition"));
}
}
private void addExpression(Piece p, ResourceWrapper exp, String label, String url) {
XhtmlNode x = new XhtmlNode(NodeType.Element, "li").style("font-size: 11px");
p.addHtml(x);
CanonicalResource cr = (CanonicalResource) context.getContext().fetchResource(Resource.class, url);
if (cr != null && cr.hasWebPath()) {
x.ah(cr.getWebPath()).tx(label);
} else {
x.ah(url).tx(label);
}
x.tx(": ");
x.code(exp.primitiveValue("expression"));
}
private void renderLogic(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws FHIRException, IOException {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context, context.getDestDir(), context.isInlineGraphics(), true, "");
TableModel model = gen.new TableModel("qtree="+q.getId(), true);
model.setAlternating(true);
if (context.getRules() == GenerationRules.VALID_RESOURCE || context.isInlineGraphics()) {
model.setDocoImg(HierarchicalTableGenerator.help16AsData());
} else {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_LINKID), context.formatPhrase(RenderingContext.QUEST_LINK), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_DESC_CONST), context.formatPhrase(RenderingContext.QUEST_ADD_INFO), null, 0));
if (!q.has("item")) {
gen.emptyRow(model, 2);
} else {
for (ResourceWrapper i : q.children("item")) {
renderLogicItem(status, gen, model.getRows(), q, i);
}
}
XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null);
x.addChildNode(xn);
}
private void renderLogicItem(RenderingStatus status, HierarchicalTableGenerator gen, List rows, ResourceWrapper q, ResourceWrapper i) throws IOException {
Row r = gen.new Row();
rows.add(r);
String type = i.primitiveValue("type");
r.setIcon("icon-q-"+type.toLowerCase()+".png", type);
r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), i.primitiveValue("linkId"), null, null));
Cell defn = gen.new Cell();
r.getCells().add(defn);
if (i.has("maxLength")) {
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH)+" "), null));
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("maxLength"), null));
}
if (i.has("definition")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.GENERAL_DEFINITION_COLON)+" "), null));
genDefinitionLink(gen, i, defn, q);
}
if (i.has("enableWhen")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_ENABLE)+" "), null));
defn.getPieces().add(gen.new Piece(null, context.formatPhrase(RenderingContext.GENERAL_TODO), null));
}
if (i.has("answerValueSet")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_VALUE)+" "), null));
if (Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) {
ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1));
if (vs == null) {
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null));
} else {
defn.getPieces().add(gen.new Piece(vs.getWebPath(), RendererFactory.factory(vs, context.forContained()).buildSummary(vs), null));
}
} else {
ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"), q.getResourceNative());
if (vs == null || !vs.hasWebPath()) {
defn.getPieces().add(gen.new Piece(null, i.primitiveValue("answerValueSet"), null));
} else {
defn.getPieces().add(gen.new Piece(vs.getWebPath(), vs.present(), null));
}
}
}
if (i.has("answerOption")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_OPTIONS)+" "), null));
defn.getPieces().add(gen.new Piece(context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), null));
}
if (i.has("initial")) {
for (ResourceWrapper v : i.children("initial")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
ResourceWrapper vv = v.child("value");
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_INITIAL)+" "), null));
defn.getPieces().add(gen.new Piece(null, vv.fhirType(), null));
defn.getPieces().add(gen.new Piece(null, " = ", null));
if (vv.isPrimitive()) {
defn.getPieces().add(gen.new Piece(null, vv.primitiveValue(), null));
} else if (vv.fhirType().equals("Coding")) {
renderCoding(gen, defn.getPieces(), vv);
} else if (vv.fhirType().equals("Coding")) {
renderQuantity(gen, defn.getPieces(), vv, false);
} else if (vv.fhirType().equals("Coding")) {
renderReference(q, gen, defn.getPieces(), vv, false);
// } else if (v.hasValueAttachment()) {
// renderAttachment(gen, defn.getPieces(), v.getValueAttachment());
}
}
}
// still todo
//
//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-choiceColumn
//
//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-width
//http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod
//http://hl7.org/fhir/StructureDefinition/Questionnaire-itemControl
//http://hl7.org/fhir/StructureDefinition/Questionnaire-sliderStepValue
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, (context.formatPhrase(RenderingContext.QUEST_EXP)+" "), null));
Piece p = gen.new Piece("ul");
defn.getPieces().add(p);
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_INT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_ITEM_CONT), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_EN), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CALC), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression");
}
for (ResourceWrapper e : i.extensions("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression")) {
addExpression(p, e.child("value"), context.formatPhrase(RenderingContext.QUEST_CAND), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression");
}
}
for (ResourceWrapper c : i.children("item")) {
renderLogicItem(status, gen, r.getSubRows(), q, c);
}
}
public void renderForm(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws UnsupportedEncodingException, IOException {
XhtmlNode d = x.div();
boolean hasPrefix = false;
for (ResourceWrapper c : q.children("item")) {
hasPrefix = hasPrefix || doesItemHavePrefix(c);
}
int i = 1;
for (ResourceWrapper c : q.children("item")) {
renderFormItem(status, d, q, c, hasPrefix ? null : Integer.toString(i), 0);
i++;
}
}
private boolean doesItemHavePrefix(ResourceWrapper i) {
if (i.has("prefix")) {
return true;
}
for (ResourceWrapper c : i.children("item")) {
if (doesItemHavePrefix(c)) {
return true;
}
}
return false;
}
private void renderFormItem(RenderingStatus status, XhtmlNode x, ResourceWrapper q, ResourceWrapper i, String pfx, int indent) throws IOException {
boolean hasExt = false;
XhtmlNode d = x.div().style("width: "+Integer.toString(900-indent*10)+"px; border-top: 1px #eeeeee solid");
if (indent > 0) {
d.style("margin-left: "+Integer.toString(10*indent)+"px");
}
XhtmlNode display = d.div().style("display: inline-block; width: "+Integer.toString(500-indent*10)+"px");
XhtmlNode details = d.div().style("border: 1px #ccccff solid; padding: 2px; display: inline-block; background-color: #fefce7; width: 380px");
XhtmlNode p = display.para();
String type = i.primitiveValue("type");
String typeT = getTranslatedCode(i.child("type"));
if ("group".equals(type)) {
p = p.b();
}
if (i.has("prefix")) {
p.tx(i.primitiveValue("prefix"));
p.tx(": ");
}
p.span(null, "linkId: "+i.primitiveValue("linkId")).tx(i.primitiveValue("text"));
if ("true".equals(i.primitiveValue("required"))) {
p.span("color: red", context.formatPhrase(RenderingContext.QUEST_MAND)).tx("*");
}
XhtmlNode input = null;
switch (type) {
case "string":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "text", typeT, 60);
break;
case "attachment":
break;
case "boolean":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "checkbox", typeT, 1);
break;
case "coding":
input = p.select(i.primitiveValue("linkId"));
listOptions(q, i, input);
break;
case "date":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "date", typeT, 10);
break;
case "dateTime":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "datetime-local", typeT, 25);
break;
case "decimal":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "number", typeT, 15);
break;
case "display":
break;
case "group":
break;
case "integer":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "number", typeT, 10);
break;
case "qantity":
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "number", "value", 15);
p.tx(" ");
input = p.input(i.primitiveValue("linkId"), "unit", "unit", 10);
break;
case "question":
break;
case "reference":
break;
case "text":
break;
case "time":
break;
case "url":
break;
default:
break;
}
if (input != null) {
if ("true".equals(i.primitiveValue("readOnly"))) {
input.attribute("readonly", "1");
input.style("background-color: #eeeeee");
}
}
// if (i.hasExtension(ToolingExtensions.EXT_Q_CHOICE_ORIENT)) {
// String code = ToolingExtensions.readStringExtension(i, ToolingExtensions.EXT_Q_CHOICE_ORIENT);
// 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"))));
//}
XhtmlNode ul = details.ul();
boolean hasFlag = false;
XhtmlNode flags = item(ul, "Flags");
item(ul, "linkId", i.primitiveValue("linkId"));
if ("true".equals(i.extensionString("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject"))) {
hasFlag = true;
flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject", "StructureDefinition-sdc-questionnaire-isSubject.html"), context.formatPhrase(RenderingContext.QUEST_SUBJECT)).img(getImgPath("icon-qi-subject.png"), "icon");
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) {
hasFlag = true;
flags.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "extension-questionnaire-hidden.html"), context.formatPhrase(RenderingContext.QUEST_HIDDEN)).img(getImgPath("icon-qi-hidden.png"), "icon");
d.style("background-color: #eeeeee");
}
if ("true".equals(i.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) {
hasFlag = true;
flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-optionalDisplay", "StructureDefinition-sdc-questionnaire-optionalDisplay.html"), context.formatPhrase(RenderingContext.QUEST_DISPLAY)).img(getImgPath("icon-qi-optional.png"), "icon");
}
if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod")) {
hasFlag = true;
flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod", "StructureDefinition-sdc-questionnaire-observationLinkPeriod.html"), context.formatPhrase(RenderingContext.QUEST_LINKED)).img(getImgPath("icon-qi-observation.png"), "icon");
}
if (i.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) {
ResourceWrapper cc = i.extension(ToolingExtensions.EXT_Q_DISPLAY_CAT).child("value");
String code = getCodeFromCC(cc, "http://hl7.org/fhir/questionnaire-display-category");
hasFlag = true;
flags.ah("https://hl7.org/fhir/R4/extension-questionnaire-displayCategory.html", (context.formatPhrase(RenderingContext.QUEST_CAT, code)+" ")).img(getImgPath("icon-qi-" + code + ".png"), "icon");
}
if (i.has("maxLength")) {
item(ul, context.formatPhrase(RenderingContext.GENERAL_MAX_LENGTH), i.primitiveValue("maxLength"));
}
if (i.has("definition")) {
genDefinitionLink(item(ul, context.formatPhrase(RenderingContext.GENERAL_DEFINITION_COLON)), i, q);
}
if (i.has("enableWhen")) {
item(ul, context.formatPhrase(RenderingContext.QUEST_EN), "todo");
}
if (i.has("answerValueSet")) {
XhtmlNode ans = item(ul, context.formatPhrase(RenderingContext.QUEST_ANSWERS));
if (!Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) {
ResourceWrapper vs = q.getContained(i.primitiveValue("answerValueSet").substring(1));
if (vs == null) {
ans.tx(i.primitiveValue("answerValueSet"));
} else if (vs.getWebPath() == null) {
ans.ah(context.prefixLocalHref("#hc"+vs.getScopedId())).tx(RendererFactory.factory(vs, context.forContained()).buildSummary(vs));
} else {
ans.ah(context.prefixLocalHref(vs.getWebPath())).tx(RendererFactory.factory(vs, context.forContained()).buildSummary(vs));
}
} else {
ValueSet vs = context.getWorker().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"), q.getResourceNative());
if (vs == null || !vs.hasWebPath()) {
ans.tx(i.primitiveValue("answerValueSet"));
} else {
ans.ah(vs.getWebPath()).tx(vs.present());
}
}
}
if (i.has("answerOption")) {
item(ul, context.formatPhrase(RenderingContext.QUEST_ANSWERS), Integer.toString(i.children("answerOption").size())+" "+Utilities.pluralize("option", i.children("answerOption").size()), context.getDefinitionsTarget()+"#item."+i.primitiveValue("linkId"));
}
if (i.has("initial")) {
XhtmlNode vi = item(ul, context.formatPhrase(RenderingContext.QUEST_INT));
boolean first = true;
for (ResourceWrapper v : i.children("initial")) {
if (first) first = false; else vi.tx(", ");
ResourceWrapper vv = v.child("value");
if (vv.isPrimitive()) {
vi.tx(vv.primitiveValue());
} else if (vv.fhirType().equals("Coding")) {
renderCoding(status, vi, vv);
} else if (vv.fhirType().equals("Reference")) {
renderReference(status, vi, vv);
} else if (vv.fhirType().equals("Quantity")) {
renderQuantity(status, vi, vv);
// } else if (v.hasValueAttachment()) {
// renderAttachment(vi, v.getValueAttachment());
}
}
}
if (!hasFlag) {
ul.remove(flags);
}
// if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) {
// if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
// defn.getPieces().add(gen.new Piece(null, "Expressions: ", null));
// Piece p = gen.new Piece("ul");
// defn.getPieces().add(p);
// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression")) {
// addExpression(p, e.getValueExpression(), "Initial Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-initialExpression");
// }
// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression")) {
// addExpression(p, e.getValueExpression(), "Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-contextExpression");
// }
// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext")) {
// addExpression(p, e.getValueExpression(), "Item Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-itemContext");
// }
// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression")) {
// addExpression(p, e.getValueExpression(), "Enable When", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-enableWhenExpression");
// }
// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression")) {
// addExpression(p, e.getValueExpression(), "Calculated Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-calculatedExpression");
// }
// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression")) {
// addExpression(p, e.getValueExpression(), "Candidates", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-candidateExpression");
// }
// }
//
int t = 1;
for (ResourceWrapper c : i.children("item")) {
renderFormItem(status, x, q, c, pfx == null ? null : pfx+"."+Integer.toString(t), indent+1);
t++;
}
}
@Nonnull
private String getImgPath(String code) throws IOException {
return context.getLocalPrefix().length() > 0
? Utilities.path(context.getLocalPrefix(), code)
: Utilities.path(code);
}
private void item(XhtmlNode ul, String name, String value, String valueLink) {
if (!Utilities.noString(value)) {
ul.li().style("font-size: 10px").ah(context.prefixLocalHref(valueLink)).tx(name+": "+value);
}
}
private void item(XhtmlNode ul, String name, String value) {
if (!Utilities.noString(value)) {
ul.li().style("font-size: 10px").tx(name+": "+value);
}
}
private XhtmlNode item(XhtmlNode ul, String name) {
XhtmlNode li = ul.li();
li.style("font-size: 10px").tx(name+": ");
return li;
}
private void listOptions(ResourceWrapper q, ResourceWrapper i, XhtmlNode select) {
if (i.has("answerValueSet")) {
ValueSet vs = null;
if (!Utilities.noString(i.primitiveValue("answerValueSet")) && i.primitiveValue("answerValueSet").startsWith("#")) {
ResourceWrapper contained = q.getContained(i.primitiveValue("answerValueSet").substring(1));
vs = contained == null ? null : (ValueSet) contained.getResourceNative();
if (vs != null && !vs.hasUrl()) {
vs = vs.copy();
vs.setUrl(q.primitiveValue("url")+"--"+contained);
}
} else {
vs = context.getContext().findTxResource(ValueSet.class, i.primitiveValue("answerValueSet"), q.getResourceNative());
}
if (vs != null) {
ValueSetExpansionOutcome exp = context.getContext().expandVS(vs, true, false);
if (exp.getValueset() != null) {
for (ValueSetExpansionContainsComponent cc : exp.getValueset().getExpansion().getContains()) {
select.option(cc.getCode(), cc.hasDisplay() ? cc.getDisplay() : cc.getCode(), false);
}
return;
}
}
} else if (i.has("answerOption")) {
renderItemOptions(select, i);
}
select.option("a", "??", false);
}
private void renderLinks(RenderingStatus status, XhtmlNode x, ResourceWrapper q) {
x.para().tx(context.formatPhrase(RenderingContext.QUEST_TRY));
XhtmlNode ul = x.ul();
ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(context.formatPhrase(RenderingContext.QUEST_NLM));
}
private void renderDefns(RenderingStatus status, XhtmlNode x, ResourceWrapper q) throws IOException {
XhtmlNode tbl = x.table("dict", false);
renderRootDefinition(status, tbl, q, new ArrayList<>());
for (ResourceWrapper qi : q.children("item")) {
renderDefinition(status, tbl, q, qi, new ArrayList<>());
}
}
private void renderRootDefinition(RenderingStatus status, XhtmlNode tbl, ResourceWrapper q, List parents) throws IOException {
boolean ext = false;
XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent");
td.an(context.prefixAnchor(q.getId()));
td.img(getImgPath("icon_q_root.gif"), "icon");
td.tx(" "+(context.formatPhrase(RenderingContext.QUEST_QUEST)+" "));
td.b().tx(q.getId());
// general information
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_URL), q.primitiveValue("url"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_VER), q.primitiveValue("version"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_NAME), q.primitiveValue("name"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_TITLE), q.primitiveValue("title"));
if (q.has("derivedFrom")) {
td = defn(tbl, context.formatPhrase(RenderingContext.QUEST_DERIVED));
boolean first = true;
for (ResourceWrapper c : q.children("derivedFrom")) {
if (first) first = false; else td.tx(", ");
td.tx(c.primitiveValue()); // todo: make these a reference
}
}
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_STATUS), q.primitiveValue("status"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_EXPER), q.primitiveValue("experimental"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_PUB), q.primitiveValue("date"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_APP), q.primitiveValue("approvalDate"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_REV_DATE), q.primitiveValue("lastReviewDate"));
if (q.has("effectivePeriod")) {
renderPeriod(status, defn(tbl, context.formatPhrase(RenderingContext.QUEST_EFF_PERIOD)), q.child("effectivePeriod"));
}
if (q.has("subjectType")) {
td = defn(tbl, context.formatPhrase(RenderingContext.QUEST_SUB_TYPE));
boolean first = true;
for (ResourceWrapper c : q.children("subjectType")) {
if (first) first = false; else td.tx(", ");
td.tx(c.primitiveValue());
}
}
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DESC), q.primitiveValue("description"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_PURPOSE), q.primitiveValue("purpose"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_COPYRIGHT), q.primitiveValue("copyright"));
if (q.has("code")) {
td = defn(tbl, Utilities.pluralize("Code", q.children("code").size()));
boolean first = true;
for (ResourceWrapper c : q.children("code")) {
if (first) first = false; else td.tx(", ");
renderCodingWithDetails(status, td, c);
}
}
}
private void renderDefinition(RenderingStatus status, XhtmlNode tbl, ResourceWrapper q, ResourceWrapper qi, List parents) throws IOException {
XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent");
td.an(context.prefixAnchor("item."+qi.primitiveValue("linkId")));
for (ResourceWrapper p : parents) {
td.ah(context.prefixLocalHref("#item."+p.primitiveValue("linkId"))).img(getImgPath("icon_q_item.png"), "icon");
td.tx(" > ");
}
td.img(getImgPath("icon_q_item.png"), "icon");
td.tx(" Item ");
td.b().tx(qi.primitiveValue("linkId"));
String type = qi.primitiveValue("type");
// general information
defn(tbl, context.formatPhrase(RenderingContext.QUEST_ID), qi.primitiveValue("linkId"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_PREFIX), qi.primitiveValue("prefix"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_TEXT), qi.primitiveValue("text"));
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_TYPE), type);
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_REQUIRED), qi.primitiveValue("required"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_REP), qi.primitiveValue("repeats"));
defn(tbl, context.formatPhrase(RenderingContext.QUEST_READ_ONLY), qi.primitiveValue("readOnly"));
if ("true".equals(qi.extensionString("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject"))) {
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_SUBJ), "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-isSubject", "This element changes who the subject of the question is", null);
}
// content control
defn(tbl, context.formatPhrase(RenderingContext.QUEST_MAX_LENGTH), qi.primitiveValue("maxLength"));
if (qi.has("answerValueSet")) {
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_VALUESET), qi.primitiveValue("definition"), context.getWorker().findTxResource(ValueSet.class, qi.primitiveValue("answerValueSet"), q.getResourceNative()));
}
if (qi.has("answerOption")) {
XhtmlNode tr = tbl.tr();
tr.td().tx(context.formatPhrase(RenderingContext.QUEST_ALLOWED));
XhtmlNode ul = tr.td().ul();
for (ResourceWrapper ans : qi.children("answerOption")) {
XhtmlNode li = ul.li();
renderDataType(status, li, ans.child("value"));
if ("true".equals(ans.primitiveValue("initialSelected"))) {
li.tx(" "+(context.formatPhrase(RenderingContext.QUEST_INITIALLY)));
}
}
}
if (qi.has("initial")) {
XhtmlNode tr = tbl.tr();
tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.QUEST_INITIAL_ANSWER)), qi.children("initial").size()));
if (qi.children("initial").size() == 1) {
renderDataType(status, tr.td(), qi.firstChild("initial").child("value"));
} else {
XhtmlNode ul = tr.td().ul();
for (ResourceWrapper ans : qi.children("initial")) {
XhtmlNode li = ul.li();
renderDataType(status, li, ans.child("value"));
}
}
}
// appearance
if (qi.hasExtension(ToolingExtensions.EXT_Q_DISPLAY_CAT)) {
XhtmlNode tr = tbl.tr();
tr.td().ah(ToolingExtensions.EXT_Q_DISPLAY_CAT).tx("Display Category");
renderDataType(status, tr.td(), qi.extension(ToolingExtensions.EXT_Q_DISPLAY_CAT).child("value"));
}
if ("true".equals(qi.extensionString(ToolingExtensions.EXT_Q_HIDDEN))) {
defn(tbl, context.formatPhrase(RenderingContext.QUEST_HIDDEN_ITEM), ToolingExtensions.EXT_Q_DISPLAY_CAT, "This item is a hidden question", null);
}
if ("true".equals(qi.extensionString(ToolingExtensions.EXT_Q_OTP_DISP))) {
defn(tbl, context.formatPhrase(RenderingContext.QUEST_HIDDEN_ITEM), ToolingExtensions.EXT_Q_OTP_DISP, "This item is optional to display", null);
}
// formal definitions
if (qi.has("definition")) {
genDefinitionLink(defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION)), qi, q);
}
if (qi.has("code")) {
XhtmlNode tr = tbl.tr();
tr.td().tx(Utilities.pluralize(context.formatPhrase(RenderingContext.GENERAL_CODE), qi.children("code").size()));
XhtmlNode ul = tr.td().ul();
for (ResourceWrapper c : qi.children("code")) {
renderCodingWithDetails(status, ul.li(), c);
}
}
if (qi.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod")) {
XhtmlNode tr = tbl.tr();
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, ToolingExtensions.EXT_O_LINK_PERIOD);
if (sd != null && sd.hasWebPath()) {
tr.td().ah(sd.getWebPath()).tx(context.formatPhrase(RenderingContext.QUEST_OBSERVATION));
} else {
tr.td().ah("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod").tx(context.formatPhrase(RenderingContext.QUEST_OBSERVATION));
}
renderDataType(status, tr.td(), qi.extension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-Questionnaire-observationLinkPeriod").child("value"));
}
// dynamic management
if (qi.has("enableWhen")) {
XhtmlNode tr = tbl.tr();
tr.td().tx(context.formatPhrase(RenderingContext.QUEST_EN));
td = tr.td();
if (qi.children("enableWhen").size() == 1) {
renderEnableWhen(td, qi.children("enableWhen").get(0));
} else {
if (qi.has("enableBehavior")) {
td.tx(qi.primitiveValue("enableBehavior")+" "+(context.formatPhrase(RenderingContext.QUEST_TRUE)));
} else {
td.tx(context.formatPhrase(RenderingContext.QUEST_ARE_TRUE));
}
XhtmlNode ul = td.ul();
for (ResourceWrapper ew : qi.children("enableWhen")) {
renderEnableWhen(ul.li(), ew);
}
}
}
// other stuff
List curr = new ArrayList<>();
curr.addAll(parents);
curr.add(qi);
for (ResourceWrapper qic : qi.children("item")) {
renderDefinition(status, tbl, q, qic, curr);
}
}
private void defn(XhtmlNode tbl, String name, String url, Resource res) throws UnsupportedEncodingException, IOException {
if (res != null && res.hasWebPath()) {
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), RendererFactory.factory(res, context.forContained()).buildSummary(wrap(res)), res.getWebPath());
} else if (Utilities.isAbsoluteUrlLinkable(url)) {
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), url, url);
} {
defn(tbl, context.formatPhrase(RenderingContext.GENERAL_DEFINITION), url);
}
}
private void renderEnableWhen(XhtmlNode x, ResourceWrapper ew) {
x.ah(context.prefixLocalHref("#item."+ew.primitiveValue("question"))).tx(ew.primitiveValue("question"));
x.tx(" ");
x.tx(ew.primitiveValue("operator"));
x.tx(" ");
x.tx(displayDataType(ew.child("Answer")));
}
private XhtmlNode defn(XhtmlNode tbl, String name) {
XhtmlNode tr = tbl.tr();
tr.td().tx(name);
return tr.td();
}
private void defn(XhtmlNode tbl, String name, int value) {
if (value > 0) {
XhtmlNode tr = tbl.tr();
tr.td().tx(name);
tr.td().tx(value);
}
}
private void defn(XhtmlNode tbl, String name, boolean value) {
XhtmlNode tr = tbl.tr();
tr.td().tx(name);
tr.td().tx(Boolean.toString(value));
}
private void defn(XhtmlNode tbl, String name, String value) {
if (!Utilities.noString(value)) {
XhtmlNode tr = tbl.tr();
tr.td().tx(name);
tr.td().tx(value);
}
}
private void defn(XhtmlNode tbl, String name, String value, String url) {
if (!Utilities.noString(value)) {
XhtmlNode tr = tbl.tr();
tr.td().tx(name);
tr.td().ah(context.prefixLocalHref(url)).tx(value);
}
}
private void defn(XhtmlNode tbl, String name, String nurl, String value, String url) {
if (!Utilities.noString(value)) {
XhtmlNode tr = tbl.tr();
tr.td().ah(context.prefixLocalHref(nurl)).tx(name);
if (url != null) {
tr.td().ah(context.prefixLocalHref(url)).tx(value);
} else {
tr.td().tx(value);
}
}
}
private void defn(XhtmlNode tbl, String name, boolean value, boolean ifFalse) {
if (ifFalse || value) {
XhtmlNode tr = tbl.tr();
tr.td().tx(name);
tr.td().tx(Boolean.toString(value));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy