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