001package org.hl7.fhir.r5.renderers; 002 003import java.io.IOException; 004import java.io.UnsupportedEncodingException; 005import java.util.List; 006 007import org.hl7.fhir.r5.model.Base; 008import org.hl7.fhir.r5.model.DataType; 009import org.hl7.fhir.r5.model.Expression; 010import org.hl7.fhir.r5.model.QuestionnaireResponse; 011import org.hl7.fhir.r5.model.QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent; 012import org.hl7.fhir.r5.model.QuestionnaireResponse.QuestionnaireResponseItemComponent; 013import org.hl7.fhir.r5.model.Resource; 014import org.hl7.fhir.r5.model.StructureDefinition; 015import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper; 016import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper; 017import org.hl7.fhir.r5.renderers.utils.RenderingContext; 018import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType; 019import org.hl7.fhir.utilities.Utilities; 020import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator; 021import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell; 022import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece; 023import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Row; 024import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.TableModel; 025import org.hl7.fhir.utilities.xhtml.NodeType; 026import org.hl7.fhir.utilities.xhtml.XhtmlNode; 027 028public class QuestionnaireResponseRenderer extends ResourceRenderer { 029 030 public QuestionnaireResponseRenderer(RenderingContext context) { 031 super(context); 032 } 033 034 public boolean render(XhtmlNode x, Resource q) throws UnsupportedEncodingException, IOException { 035 return render(x, (QuestionnaireResponse) q); 036 } 037 038 public boolean render(XhtmlNode x, QuestionnaireResponse q) throws UnsupportedEncodingException, IOException { 039 switch (context.getQuestionnaireMode()) { 040 case FORM: return renderForm(x, q); 041 case LINKS: return renderLinks(x, q); 042// case LOGIC: return renderLogic(x, q); 043// case DEFNS: return renderDefns(x, q); 044 case TREE: return renderTree(x, q); 045 default: 046 throw new Error("Unknown QuestionnaireResponse Renderer Mode"); 047 } 048 } 049 050 public boolean render(XhtmlNode x, ResourceWrapper qr) throws UnsupportedEncodingException, IOException { 051 switch (context.getQuestionnaireMode()) { 052 case FORM: return renderTree(x, qr); 053 case LINKS: return renderLinks(x, qr); 054// case LOGIC: return renderLogic(x, q); 055// case DEFNS: return renderDefns(x, q); 056 case TREE: return renderTree(x, qr); 057 default: 058 throw new Error("Unknown QuestionnaireResponse Renderer Mode"); 059 } 060 } 061 062 public boolean renderTree(XhtmlNode x, ResourceWrapper qr) throws UnsupportedEncodingException, IOException { 063 HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true); 064 TableModel model = gen.new TableModel("qtree="+qr.getId(), false); 065 model.setAlternating(true); 066 model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png"); 067 model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); 068 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0)); 069 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0)); 070 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Definition"), translate("sd.hint", "Minimum and Maximum # of times the the itemcan appear in the instance"), null, 0)); 071 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Answer"), translate("sd.hint", "The type of the item"), null, 0)); 072 073 boolean hasExt = false; 074 // first we add a root for the questionaire itself 075 Row row = addTreeRoot(gen, model.getRows(), qr); 076 List<BaseWrapper> items = qr.children("item"); 077 for (BaseWrapper i : items) { 078 hasExt = renderTreeItem(gen, row.getSubRows(), qr, i) || hasExt; 079 } 080 XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); 081 x.getChildNodes().add(xn); 082 return hasExt; 083 } 084 085 public boolean renderTree(XhtmlNode x, QuestionnaireResponse q) throws UnsupportedEncodingException, IOException { 086 HierarchicalTableGenerator gen = new HierarchicalTableGenerator(context.getDestDir(), context.isInlineGraphics(), true); 087 TableModel model = gen.new TableModel("qtree="+q.getId(), true); 088 model.setAlternating(true); 089 model.setDocoImg(context.getLink(KnownLinkType.SPEC) +"help16.png"); 090 model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table"); 091 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "LinkId"), translate("sd.hint", "The linkId for the item"), null, 0)); 092 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Text"), translate("sd.hint", "Text for the item"), null, 0)); 093 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Definition"), translate("sd.hint", "Minimum and Maximum # of times the the itemcan appear in the instance"), null, 0)); 094 model.getTitles().add(gen.new Title(null, model.getDocoRef(), translate("sd.head", "Answer"), translate("sd.hint", "The type of the item"), null, 0)); 095 096 boolean hasExt = false; 097 // first we add a root for the questionaire itself 098 Row row = addTreeRoot(gen, model.getRows(), q); 099 for (QuestionnaireResponseItemComponent i : q.getItem()) { 100 hasExt = renderTreeItem(gen, row.getSubRows(), q, i) || hasExt; 101 } 102 XhtmlNode xn = gen.generate(model, context.getLocalPrefix(), 1, null); 103 x.getChildNodes().add(xn); 104 return hasExt; 105 } 106 107 108 109 private Row addTreeRoot(HierarchicalTableGenerator gen, List<Row> rows, QuestionnaireResponse q) throws IOException { 110 Row r = gen.new Row(); 111 rows.add(r); 112 113 r.setIcon("icon_q_root.gif", "QuestionnaireResponseRoot"); 114 r.getCells().add(gen.new Cell(null, null, q.getId(), null, null)); 115 r.getCells().add(gen.new Cell(null, null, "", null, null)); 116 r.getCells().add(gen.new Cell(null, null, "QuestionnaireResponse", null, null)); 117 r.getCells().add(gen.new Cell(null, null, "", null, null)); 118 return r; 119 } 120 121 private Row addTreeRoot(HierarchicalTableGenerator gen, List<Row> rows, ResourceWrapper q) throws IOException { 122 Row r = gen.new Row(); 123 rows.add(r); 124 125 r.setIcon("icon_q_root.gif", "QuestionnaireResponseRoot"); 126 r.getCells().add(gen.new Cell(null, null, q.getId(), null, null)); 127 r.getCells().add(gen.new Cell(null, null, "", null, null)); 128 r.getCells().add(gen.new Cell(null, null, "QuestionnaireResponse", null, null)); 129 r.getCells().add(gen.new Cell(null, null, "", null, null)); 130 return r; 131 } 132 133 134 135 private boolean renderTreeItem(HierarchicalTableGenerator gen, List<Row> rows, ResourceWrapper q, BaseWrapper i) throws IOException { 136 Row r = gen.new Row(); 137 rows.add(r); 138 boolean hasExt = false; 139 140 List<BaseWrapper> items = i.children("item"); 141 List<BaseWrapper> answers = i.children("answer"); 142 boolean hasItem = items != null && !items.isEmpty(); 143 if (answers != null) { 144 for (BaseWrapper a : answers) { 145 hasItem = a.has("item"); 146 } 147 } 148 if (hasItem) { 149 r.setIcon("icon-q-group.png", "Group"); 150 } else { 151 r.setIcon("icon-q-string.png", "Item"); 152 } 153 String linkId = i.has("linkId") ? i.get("linkId").primitiveValue() : "??"; 154 String text = i.has("text") ? i.get("text").primitiveValue() : ""; 155 r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+linkId, linkId, null, null)); 156 r.getCells().add(gen.new Cell(null, null, text, null, null)); 157 r.getCells().add(gen.new Cell(null, null, null, null, null)); 158 if (answers == null || answers.size() == 0) { 159 r.getCells().add(gen.new Cell(null, null, null, null, null)); 160 if (items != null) { 161 for (BaseWrapper si : items) { 162 renderTreeItem(gen, r.getSubRows(), q, si); 163 } 164 } 165 } else if (answers.size() == 1) { 166 BaseWrapper ans = answers.get(0); 167 renderAnswer(gen, q, r, ans); 168 } else { 169 r.getCells().add(gen.new Cell(null, null, null, null, null)); 170 for (BaseWrapper ans : answers) { 171 Row ar = gen.new Row(); 172 ar.setIcon("icon-q-string.png", "Item"); 173 ar.getSubRows().add(ar); 174 ar.getCells().add(gen.new Cell(null, null, null, null, null)); 175 ar.getCells().add(gen.new Cell(null, null, text, null, null)); 176 ar.getCells().add(gen.new Cell(null, null, null, null, null)); 177 renderAnswer(gen, q, ar, ans); 178 } 179 } 180 181 return hasExt; 182 } 183 184 public void renderAnswer(HierarchicalTableGenerator gen, ResourceWrapper q, Row r, BaseWrapper ans) throws UnsupportedEncodingException, IOException { 185 List<BaseWrapper> items; 186 Base b = ans.get("value[x]"); 187 if (b == null) { 188 r.getCells().add(gen.new Cell(null, null, "null!", null, null)); 189 } else if (b.isPrimitive()) { 190 r.getCells().add(gen.new Cell(null, null, b.primitiveValue(), null, null)); 191 } else { 192 XhtmlNode x = new XhtmlNode(NodeType.Element, "span"); 193 Cell cell = gen.new Cell(null, null, null, null, null); 194 Piece p = gen.new Piece("span"); 195 p.getChildren().add(x); 196 cell.addPiece(p); 197 render(x, (DataType) b); 198 r.getCells().add(cell); 199 } 200 items = ans.children("item"); 201 for (BaseWrapper si : items) { 202 renderTreeItem(gen, r.getSubRows(), q, si); 203 } 204 } 205 206 private boolean renderTreeItem(HierarchicalTableGenerator gen, List<Row> rows, QuestionnaireResponse q, QuestionnaireResponseItemComponent i) throws IOException { 207 Row r = gen.new Row(); 208 rows.add(r); 209 boolean hasExt = false; 210 211 boolean hasItem = i.hasItem(); 212 for (QuestionnaireResponseItemAnswerComponent a : i.getAnswer()) { 213 hasItem = a.hasItem(); 214 } 215 if (hasItem) { 216 r.setIcon("icon-q-group.png", "Group"); 217 } else { 218 r.setIcon("icon-q-string.png", "Item"); 219 } 220 r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.getLinkId(), i.getLinkId(), null, null)); 221 r.getCells().add(gen.new Cell(null, null, i.getText(), null, null)); 222 r.getCells().add(gen.new Cell(null, null, null, null, null)); 223 r.getCells().add(gen.new Cell(null, null, null, null, null)); 224 225 return hasExt; 226 } 227 228 public void genDefinitionLink(HierarchicalTableGenerator gen, QuestionnaireResponseItemComponent i, Cell defn, Resource src) { 229 // can we resolve the definition? 230 String path = null; 231 String d = i.getDefinition(); 232 if (d.contains("#")) { 233 path = d.substring(d.indexOf("#")+1); 234 d = d.substring(0, d.indexOf("#")); 235 } 236 StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, src); 237 if (sd != null) { 238 String url = sd.getUserString("path"); 239 if (url != null) { 240 defn.getPieces().add(gen.new Piece(url+"#"+path, path, null)); 241 } else { 242 defn.getPieces().add(gen.new Piece(null, i.getDefinition(), null)); 243 } 244 } else { 245 defn.getPieces().add(gen.new Piece(null, i.getDefinition(), null)); 246 } 247 } 248 249 public void genDefinitionLink(XhtmlNode x, QuestionnaireResponseItemComponent i, Resource src) { 250 // can we resolve the definition? 251 String path = null; 252 String d = i.getDefinition(); 253 if (d.contains("#")) { 254 path = d.substring(d.indexOf("#")+1); 255 d = d.substring(0, d.indexOf("#")); 256 } 257 StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, src); 258 if (sd != null) { 259 String url = sd.getUserString("path"); 260 if (url != null) { 261 x.ah(url+"#"+path).tx(path); 262 } else { 263 x.tx(i.getDefinition()); 264 } 265 } else { 266 x.tx(i.getDefinition()); 267 } 268 } 269 270 private void addExpression(Piece p, Expression exp, String label, String url) { 271 XhtmlNode x = new XhtmlNode(NodeType.Element, "li").style("font-size: 11px"); 272 p.addHtml(x); 273 x.ah(url).tx(label); 274 x.tx(": "); 275 x.code(exp.getExpression()); 276 } 277 278 public boolean renderForm(XhtmlNode x, QuestionnaireResponse q) throws UnsupportedEncodingException, IOException { 279 boolean hasExt = false; 280// XhtmlNode d = x.div(); 281// boolean hasPrefix = false; 282// for (QuestionnaireItemComponent c : q.getItem()) { 283// hasPrefix = hasPrefix || doesItemHavePrefix(c); 284// } 285// int i = 1; 286// for (QuestionnaireItemComponent c : q.getItem()) { 287// hasExt = renderFormItem(d, q, c, hasPrefix ? null : Integer.toString(i), 0) || hasExt; 288// i++; 289// } 290// return hasExt; 291// } 292// 293// private boolean doesItemHavePrefix(QuestionnaireItemComponent i) { 294// if (i.hasPrefix()) { 295// return true; 296// } 297// for (QuestionnaireItemComponent c : i.getItem()) { 298// if (doesItemHavePrefix(c)) { 299// return true; 300// } 301// } 302 return false; 303 } 304 305 public boolean renderForm(XhtmlNode x, ResourceWrapper q) throws UnsupportedEncodingException, IOException { 306 boolean hasExt = false; 307 XhtmlNode d = x.div(); 308 d.tx("todo"); 309// boolean hasPrefix = false; 310// for (QuestionnaireItemComponent c : q.getItem()) { 311// hasPrefix = hasPrefix || doesItemHavePrefix(c); 312// } 313// int i = 1; 314// for (QuestionnaireItemComponent c : q.getItem()) { 315// hasExt = renderFormItem(d, q, c, hasPrefix ? null : Integer.toString(i), 0) || hasExt; 316// i++; 317// } 318// return hasExt; 319// } 320// 321// private boolean doesItemHavePrefix(QuestionnaireItemComponent i) { 322// if (i.hasPrefix()) { 323// return true; 324// } 325// for (QuestionnaireItemComponent c : i.getItem()) { 326// if (doesItemHavePrefix(c)) { 327// return true; 328// } 329// } 330 return hasExt; 331 } 332 333// private boolean renderFormItem(XhtmlNode x, QuestionnaireResponse q, QuestionnaireItemComponent i, String pfx, int indent) throws IOException { 334// boolean hasExt = false; 335// XhtmlNode d = x.div().style("width: "+Integer.toString(900-indent*10)+"px; border-top: 1px #eeeeee solid"); 336// if (indent > 0) { 337// d.style("margin-left: "+Integer.toString(10*indent)+"px"); 338// } 339// XhtmlNode display = d.div().style("display: inline-block; width: "+Integer.toString(500-indent*10)+"px"); 340// XhtmlNode details = d.div().style("border: 1px #ccccff solid; padding: 2px; display: inline-block; background-color: #fefce7; width: 380px"); 341// XhtmlNode p = display.para(); 342// if (i.getType() == QuestionnaireItemType.GROUP) { 343// p = p.b(); 344// } 345// if (i.hasPrefix()) { 346// p.tx(i.getPrefix()); 347// p.tx(": "); 348// } 349// p.span(null, "linkId: "+i.getLinkId()).tx(i.getText()); 350// if (i.getRequired()) { 351// p.span("color: red", "Mandatory").tx("*"); 352// } 353// 354// XhtmlNode input = null; 355// switch (i.getType()) { 356// case STRING: 357// p.tx(" "); 358// input = p.input(i.getLinkId(), "text", i.getType().getDisplay(), 60); 359// break; 360// case ATTACHMENT: 361// break; 362// case BOOLEAN: 363// p.tx(" "); 364// input = p.input(i.getLinkId(), "checkbox", i.getType().getDisplay(), 1); 365// break; 366// case CHOICE: 367// input = p.select(i.getLinkId()); 368// listOptions(q, i, input); 369// break; 370// case DATE: 371// p.tx(" "); 372// input = p.input(i.getLinkId(), "date", i.getType().getDisplay(), 10); 373// break; 374// case DATETIME: 375// p.tx(" "); 376// input = p.input(i.getLinkId(), "datetime-local", i.getType().getDisplay(), 25); 377// break; 378// case DECIMAL: 379// p.tx(" "); 380// input = p.input(i.getLinkId(), "number", i.getType().getDisplay(), 15); 381// break; 382// case DISPLAY: 383// break; 384// case GROUP: 385// 386// break; 387// case INTEGER: 388// p.tx(" "); 389// input = p.input(i.getLinkId(), "number", i.getType().getDisplay(), 10); 390// break; 391// case OPENCHOICE: 392// break; 393// case QUANTITY: 394// p.tx(" "); 395// input = p.input(i.getLinkId(), "number", "value", 15); 396// p.tx(" "); 397// input = p.input(i.getLinkId(), "unit", "unit", 10); 398// break; 399// case QUESTION: 400// break; 401// case REFERENCE: 402// break; 403// case TEXT: 404// break; 405// case TIME: 406// break; 407// case URL: 408// break; 409// default: 410// break; 411// } 412// if (input != null) { 413// if (i.getReadOnly()) { 414// input.attribute("readonly", "1"); 415// input.style("background-color: #eeeeee"); 416// } 417// } 418// 419//// if (i.hasExtension(" http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-choiceOrientation")) { 420//// String code = ToolingExtensions.readStringExtension(i, "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-choiceOrientation"); 421//// 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")))); 422////} 423// 424// 425// XhtmlNode ul = details.ul(); 426// boolean hasFlag = false; 427// XhtmlNode flags = item(ul, "Flags"); 428// item(ul, "linkId", i.getLinkId()); 429// 430// if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-isSubject")) { 431// hasFlag = true; 432// flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-isSubject", "Can change the subject of the QuestionnaireResponse").img(Utilities.path(context.getLocalPrefix(), "icon-qi-subject.png")); 433// } 434// if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-hidden")) { 435// hasFlag = true; 436// flags.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "extension-QuestionnaireResponse-hidden.html"), "Is a hidden item").img(Utilities.path(context.getLocalPrefix(), "icon-qi-hidden.png")); 437// d.style("background-color: #eeeeee"); 438// } 439// if (ToolingExtensions.readBoolExtension(i, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-optionalDisplay")) { 440// hasFlag = true; 441// flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-optionalDisplay", "Is optional to display").img(Utilities.path(context.getLocalPrefix(), "icon-qi-optional.png")); 442// } 443// if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod")) { 444// hasFlag = true; 445// flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod", "Is linked to an observation").img(Utilities.path(context.getLocalPrefix(), "icon-qi-observation.png")); 446// } 447// if (i.hasExtension(" http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory")) { 448// CodeableConcept cc = i.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory").getValueCodeableConcept(); 449// String code = cc.getCode("http://hl7.org/fhir/QuestionnaireResponse-display-category"); 450// hasFlag = true; 451// flags.ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-displayCategory", "Category: "+code).img(Utilities.path(context.getLocalPrefix(), "icon-qi-"+code+".png")); 452// } 453// 454// if (i.hasMaxLength()) { 455// item(ul, "Max Length", Integer.toString(i.getMaxLength())); 456// } 457// if (i.hasDefinition()) { 458// genDefinitionLink(item(ul, "Definition"), i); 459// } 460// if (i.hasEnableWhen()) { 461// item(ul, "Enable When", "todo"); 462// } 463// if (i.hasAnswerValueSet()) { 464// XhtmlNode ans = item(ul, "Answers"); 465// if (i.getAnswerValueSet().startsWith("#")) { 466// ValueSet vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)); 467// if (vs == null) { 468// ans.tx(i.getAnswerValueSet()); 469// } else { 470// ans.ah(vs.getUserString("path")).tx(vs.present()); 471// } 472// } else { 473// ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet()); 474// if (vs == null || !vs.hasUserData("path")) { 475// ans.tx(i.getAnswerValueSet()); 476// } else { 477// ans.ah(vs.getUserString("path")).tx(vs.present()); 478// } 479// } 480// } 481// if (i.hasAnswerOption()) { 482// item(ul, "Answers", Integer.toString(i.getAnswerOption().size())+" "+Utilities.pluralize("option", i.getAnswerOption().size()), context.getDefinitionsTarget()+"#item."+i.getLinkId()); 483// } 484// if (i.hasInitial()) { 485// XhtmlNode vi = item(ul, "Initial Values"); 486// boolean first = true; 487// for (QuestionnaireItemInitialComponent v : i.getInitial()) { 488// if (first) first = false; else vi.tx(", "); 489// if (v.getValue().isPrimitive()) { 490// vi.tx(v.getValue().primitiveValue()); 491// } else { 492// vi.tx("{todo}"); 493// } 494// } 495// } 496// if (!hasFlag) { 497// ul.remove(flags); 498// } 499//// if (i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-enableWhenExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-itemContext") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-calculatedExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-contextExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-candidateExpression") || i.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-initialExpression")) { 500//// if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); 501//// defn.getPieces().add(gen.new Piece(null, "Expressions: ", null)); 502//// Piece p = gen.new Piece("ul"); 503//// defn.getPieces().add(p); 504//// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-initialExpression")) { 505//// addExpression(p, e.getValueExpression(), "Initial Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-initialExpression"); 506//// } 507//// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-contextExpression")) { 508//// addExpression(p, e.getValueExpression(), "Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-contextExpression"); 509//// } 510//// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-itemContext")) { 511//// addExpression(p, e.getValueExpression(), "Item Context", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-itemContext"); 512//// } 513//// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-enableWhenExpression")) { 514//// addExpression(p, e.getValueExpression(), "Enable When", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-enableWhenExpression"); 515//// } 516//// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-calculatedExpression")) { 517//// addExpression(p, e.getValueExpression(), "Calculated Value", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-calculatedExpression"); 518//// } 519//// for (Extension e : i.getExtensionsByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-candidateExpression")) { 520//// addExpression(p, e.getValueExpression(), "Candidates", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-candidateExpression"); 521//// } 522//// } 523//// 524// 525// int t = 1; 526// for (QuestionnaireItemComponent c : i.getItem()) { 527// hasExt = renderFormItem(x, q, c, pfx == null ? null : pfx+"."+Integer.toString(t), indent+1) || hasExt; 528// t++; 529// } 530// return hasExt; 531// } 532// 533// private void item(XhtmlNode ul, String name, String value, String valueLink) { 534// if (!Utilities.noString(value)) { 535// ul.li().style("font-size: 10px").ah(valueLink).tx(name+": "+value); 536// } 537// } 538// 539// private void item(XhtmlNode ul, String name, String value) { 540// if (!Utilities.noString(value)) { 541// ul.li().style("font-size: 10px").tx(name+": "+value); 542// } 543// } 544// private XhtmlNode item(XhtmlNode ul, String name) { 545// XhtmlNode li = ul.li(); 546// li.style("font-size: 10px").tx(name+": "); 547// return li; 548// } 549// 550// 551// private void listOptions(QuestionnaireResponse q, QuestionnaireItemComponent i, XhtmlNode select) { 552// if (i.hasAnswerValueSet()) { 553// ValueSet vs = null; 554// if (i.getAnswerValueSet().startsWith("#")) { 555// vs = (ValueSet) q.getContained(i.getAnswerValueSet().substring(1)).copy(); 556// if (vs != null && !vs.hasUrl()) { 557// vs.setUrl("urn:uuid:"+UUID.randomUUID().toString().toLowerCase()); 558// } 559// } else { 560// vs = context.getContext().fetchResource(ValueSet.class, i.getAnswerValueSet()); 561// } 562// if (vs != null) { 563// ValueSetExpansionOutcome exp = context.getContext().expandVS(vs, true, false); 564// if (exp.getValueset() != null) { 565// for (ValueSetExpansionContainsComponent cc : exp.getValueset().getExpansion().getContains()) { 566// select.option(cc.getCode(), cc.hasDisplay() ? cc.getDisplay() : cc.getCode(), false); 567// } 568// return; 569// } 570// } 571// } else if (i.hasAnswerOption()) { 572// 573// } 574// select.option("a", "??", false); 575// } 576// 577// public String display(Resource dr) throws UnsupportedEncodingException, IOException { 578// return display((QuestionnaireResponse) dr); 579// } 580// 581// public String display(QuestionnaireResponse q) throws UnsupportedEncodingException, IOException { 582// return "QuestionnaireResponse "+q.present(); 583// } 584// 585 private boolean renderLinks(XhtmlNode x, QuestionnaireResponse q) { 586 x.para().tx("Try this QuestionnaireResponse out:"); 587 XhtmlNode ul = x.ul(); 588 ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); 589 return false; 590 } 591 592 private boolean renderLinks(XhtmlNode x, ResourceWrapper q) { 593 x.para().tx("Try this QuestionnaireResponse out:"); 594 XhtmlNode ul = x.ul(); 595 ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx("NLM Forms Library"); 596 return false; 597 } 598 599// private boolean renderDefns(XhtmlNode x, QuestionnaireResponse q) throws IOException { 600// XhtmlNode tbl = x.table("dict"); 601// boolean ext = false; 602// ext = renderRootDefinition(tbl, q, new ArrayList<>()) || ext; 603// for (QuestionnaireItemComponent qi : q.getItem()) { 604// ext = renderDefinition(tbl, q, qi, new ArrayList<>()) || ext; 605// } 606// return ext; 607// } 608// 609// private boolean renderRootDefinition(XhtmlNode tbl, QuestionnaireResponse q, List<QuestionnaireItemComponent> parents) throws IOException { 610// boolean ext = false; 611// XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent"); 612// td.an(q.getId()); 613// td.img(Utilities.path(context.getLocalPrefix(), "icon_q_root.gif")); 614// td.tx(" QuestionnaireResponse "); 615// td.b().tx(q.getId()); 616// 617// // general information 618// defn(tbl, "URL", q.getUrl()); 619// defn(tbl, "Version", q.getVersion()); 620// defn(tbl, "Name", q.getName()); 621// defn(tbl, "Title", q.getTitle()); 622// if (q.hasDerivedFrom()) { 623// td = defn(tbl, "Derived From"); 624// boolean first = true; 625// for (CanonicalType c : q.getDerivedFrom()) { 626// if (first) first = false; else td.tx(", "); 627// td.tx(c.asStringValue()); // todo: make these a reference 628// } 629// } 630// defn(tbl, "Status", q.getStatus().getDisplay()); 631// defn(tbl, "Experimental", q.getExperimental()); 632// defn(tbl, "Publication Date", q.getDateElement().primitiveValue()); 633// defn(tbl, "Approval Date", q.getApprovalDateElement().primitiveValue()); 634// defn(tbl, "Last Review Date", q.getLastReviewDateElement().primitiveValue()); 635// if (q.hasEffectivePeriod()) { 636// renderPeriod(defn(tbl, "Effective Period"), q.getEffectivePeriod()); 637// } 638// 639// if (q.hasSubjectType()) { 640// td = defn(tbl, "Subject Type"); 641// boolean first = true; 642// for (CodeType c : q.getSubjectType()) { 643// if (first) first = false; else td.tx(", "); 644// td.tx(c.asStringValue()); 645// } 646// } 647// defn(tbl, "Description", q.getDescription()); 648// defn(tbl, "Purpose", q.getPurpose()); 649// defn(tbl, "Copyright", q.getCopyright()); 650// if (q.hasCode()) { 651// td = defn(tbl, Utilities.pluralize("Code", q.getCode().size())); 652// boolean first = true; 653// for (Coding c : q.getCode()) { 654// if (first) first = false; else td.tx(", "); 655// renderCodingWithDetails(td, c); 656// } 657// } 658// return false; 659// } 660 661// private boolean renderDefinition(XhtmlNode tbl, QuestionnaireResponse q, QuestionnaireItemComponent qi, List<QuestionnaireItemComponent> parents) throws IOException { 662// boolean ext = false; 663// XhtmlNode td = tbl.tr().td("structure").colspan("2").span(null, null).attribute("class", "self-link-parent"); 664// td.an("item."+qi.getLinkId()); 665// for (QuestionnaireItemComponent p : parents) { 666// td.ah("#item."+p.getLinkId()).img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png")); 667// td.tx(" > "); 668// } 669// td.img(Utilities.path(context.getLocalPrefix(), "icon_q_item.png")); 670// td.tx(" Item "); 671// td.b().tx(qi.getLinkId()); 672// 673// // general information 674// defn(tbl, "Link Id", qi.getLinkId()); 675// defn(tbl, "Prefix", qi.getPrefix()); 676// defn(tbl, "Text", qi.getText()); 677// defn(tbl, "Type", qi.getType().getDisplay()); 678// defn(tbl, "Required", qi.getRequired(), true); 679// defn(tbl, "Repeats", qi.getRepeats(), true); 680// defn(tbl, "Read Only", qi.getReadOnly(), false); 681// if (ToolingExtensions.readBoolExtension(qi, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-isSubject")) { 682// defn(tbl, "Subject", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-isSubject", "This element changes who the subject of the question is", null); 683// } 684// 685// // content control 686// defn(tbl, "Max Length", qi.getMaxLength()); 687// if (qi.hasAnswerValueSet()) { 688// defn(tbl, "Value Set", qi.getDefinition(), context.getWorker().fetchResource(ValueSet.class, qi.getAnswerValueSet())); 689// } 690// if (qi.hasAnswerOption()) { 691// XhtmlNode tr = tbl.tr(); 692// tr.td().tx("Allowed Answers"); 693// XhtmlNode ul = tr.td().ul(); 694// for (QuestionnaireItemAnswerOptionComponent ans : qi.getAnswerOption()) { 695// XhtmlNode li = ul.li(); 696// render(li, ans.getValue()); 697// if (ans.getInitialSelected()) { 698// li.tx(" (initially selected)"); 699// } 700// } 701// } 702// if (qi.hasInitial()) { 703// XhtmlNode tr = tbl.tr(); 704// tr.td().tx(Utilities.pluralize("Initial Answer", qi.getInitial().size())); 705// if (qi.getInitial().size() == 1) { 706// render(tr.td(), qi.getInitialFirstRep().getValue()); 707// } else { 708// XhtmlNode ul = tr.td().ul(); 709// for (QuestionnaireItemInitialComponent ans : qi.getInitial()) { 710// XhtmlNode li = ul.li(); 711// render(li, ans.getValue()); 712// } 713// } 714// } 715// 716// // appearance 717// if (qi.hasExtension(" http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory")) { 718// XhtmlNode tr = tbl.tr(); 719// tr.td().ah("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory").tx("Display Category"); 720// render(tr.td(), qi.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory").getValue()); 721// } 722// if (ToolingExtensions.readBoolExtension(qi, "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-hidden")) { 723// defn(tbl, "Hidden Item", "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory", "This item is a hidden question", null); 724// } 725// if (ToolingExtensions.readBoolExtension(qi, "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-optionalDisplay")) { 726// defn(tbl, "Hidden Item", "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-optionalDisplay", "This item is optional to display", null); 727// } 728// 729// // formal definitions 730// if (qi.hasDefinition()) { 731// genDefinitionLink(defn(tbl, "Definition"), qi); 732// } 733// 734// if (qi.hasCode()) { 735// XhtmlNode tr = tbl.tr(); 736// tr.td().tx(Utilities.pluralize("Code", qi.getCode().size())); 737// XhtmlNode ul = tr.td().ul(); 738// for (Coding c : qi.getCode()) { 739// renderCodingWithDetails(ul.li(), c); 740// } 741// } 742// if (qi.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod")) { 743// XhtmlNode tr = tbl.tr(); 744// tr.td().ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod").tx("Observation Link Period"); 745// render(tr.td(), qi.getExtensionByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod").getValue()); 746// } 747// 748// // dynamic management 749// if (qi.hasEnableWhen()) { 750// XhtmlNode tr = tbl.tr(); 751// tr.td().tx("Enable When"); 752// td = tr.td(); 753// if (qi.getEnableWhen().size() == 1) { 754// renderEnableWhen(td, qi.getEnableWhen().get(0)); 755// } else { 756// td.tx(qi.getEnableBehavior().getDisplay()+" are true:"); 757// XhtmlNode ul = td.ul(); 758// for (QuestionnaireItemEnableWhenComponent ew : qi.getEnableWhen()) { 759// renderEnableWhen(ul.li(), ew); 760// } 761// } 762// } 763// 764// 765// // other stuff 766// 767// 768// 769// List<QuestionnaireItemComponent> curr = new ArrayList<>(); 770// curr.addAll(parents); 771// curr.add(qi); 772// for (QuestionnaireItemComponent qic : qi.getItem()) { 773// ext = renderDefinition(tbl, q, qic, curr) || ext; 774// } 775// return ext; 776// } 777// 778// private void defn(XhtmlNode tbl, String name, String url, Resource res) throws UnsupportedEncodingException, IOException { 779// if (res != null && res.hasUserData("path")) { 780// defn(tbl, "Definition", RendererFactory.factory(res, context).display(res), res.getUserString("path")); 781// } else if (Utilities.isAbsoluteUrl(url)) { 782// defn(tbl, "Definition", url, url); 783// } { 784// defn(tbl, "Definition", url); 785// } 786// 787// } 788// 789// private void renderEnableWhen(XhtmlNode x, QuestionnaireItemEnableWhenComponent ew) { 790// x.ah("#item."+ew.getQuestion()).tx(ew.getQuestion()); 791// x.tx(" "); 792// x.tx(ew.getOperator().toCode()); 793// x.tx(" "); 794// x.tx(display(ew.getAnswer())); 795// } 796// 797// private XhtmlNode defn(XhtmlNode tbl, String name) { 798// XhtmlNode tr = tbl.tr(); 799// tr.td().tx(name); 800// return tr.td(); 801// } 802// 803// private void defn(XhtmlNode tbl, String name, int value) { 804// if (value > 0) { 805// XhtmlNode tr = tbl.tr(); 806// tr.td().tx(name); 807// tr.td().tx(value); 808// } 809// } 810// 811// 812// private void defn(XhtmlNode tbl, String name, boolean value) { 813// XhtmlNode tr = tbl.tr(); 814// tr.td().tx(name); 815// tr.td().tx(Boolean.toString(value)); 816// } 817// 818// private void defn(XhtmlNode tbl, String name, String value) { 819// if (!Utilities.noString(value)) { 820// XhtmlNode tr = tbl.tr(); 821// tr.td().tx(name); 822// tr.td().tx(value); 823// } 824// } 825// 826// private void defn(XhtmlNode tbl, String name, String value, String url) { 827// if (!Utilities.noString(value)) { 828// XhtmlNode tr = tbl.tr(); 829// tr.td().tx(name); 830// tr.td().ah(url).tx(value); 831// } 832// } 833// 834// private void defn(XhtmlNode tbl, String name, String nurl, String value, String url) { 835// if (!Utilities.noString(value)) { 836// XhtmlNode tr = tbl.tr(); 837// tr.td().ah(nurl).tx(name); 838// if (url != null) { 839// tr.td().ah(url).tx(value); 840// } else { 841// tr.td().tx(value); 842// } 843// } 844// } 845// 846// private void defn(XhtmlNode tbl, String name, boolean value, boolean ifFalse) { 847// if (ifFalse || value) { 848// XhtmlNode tr = tbl.tr(); 849// tr.td().tx(name); 850// tr.td().tx(Boolean.toString(value)); 851// } 852// } 853 854 855 @Override 856 public String display(Resource r) throws UnsupportedEncodingException, IOException { 857 return "todo"; 858 } 859 860 @Override 861 public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException { 862 return "Not done yet"; 863 } 864 865}