package org.commcare.print; import org.commcare.cases.entity.Entity; import org.commcare.graph.model.GraphData; import org.commcare.graph.util.GraphException; import org.commcare.suite.model.DetailField; import org.commcare.util.DetailFieldPrintInfo; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import java.io.Serializable; /** * Represents a single DetailField whose information may be used to populate a placeholder in a * print template for a Detail * * Created by amstone326 on 3/2/17. */ public class PrintableDetailField implements Serializable { private static final int GRAPH_WIDTH = 750; private static final int GRAPH_HEIGHT = 375; private String valueString; private String fieldForm; public PrintableDetailField(DetailFieldPrintInfo printInfo) { DetailField field = printInfo.field; Entity entity = printInfo.entity; int fieldIndex = printInfo.index; this.fieldForm = field.getTemplateForm(); String fieldAsString = entity.getFieldString(fieldIndex); if ("".equals(fieldAsString) || fieldAsString == null) { // this field can't be automatically represented as a string if (isGraphDetailField()) { parseGraphPrintData(entity, field, fieldIndex); } else { // this field is of some other form for which printing is currently not supported this.valueString = ""; } } else { this.valueString = fieldAsString; } } private void parseGraphPrintData(Entity entity, DetailField field, int fieldIndex) { try { Object evaluatedField = entity.getField(fieldIndex); String graphTitle = field.getHeader().evaluate(); if ("".equals(graphTitle) || graphTitle == null) { // DO NOT CHANGE THIS -- Workaround to address the fact that a graph will not // render properly if the 'chart-title' <div> is empty graphTitle = " "; } String fullGraphHtml = ((GraphData)evaluatedField).getGraphHTML(graphTitle); this.valueString = fullGraphHtml; } catch (GraphException e) { this.valueString = String.format("<p>AN ERROR OCCURRED: %s</p>", e.getMessage()); } } public String getFormattedValueString() { if (isGraphDetailField()) { return createIframeForGraphHtml(valueString); } else { // Replace any ascii new line characters generated by HQ with html break tag return valueString.replaceAll("\\x0A", "<br>"); } } private static String createIframeForGraphHtml(String fullGraphHtml) { return "<iframe srcdoc=\"" + scrubHtmlStringForUseAsAttribute(addStyleAttributes(fullGraphHtml)) + "\" height=\"" + GRAPH_HEIGHT + "\" width=\"" + GRAPH_WIDTH + "\"></iframe>"; } private static String scrubHtmlStringForUseAsAttribute(String htmlString) { return htmlString.replace("\"", "\'"); } private static String addStyleAttributes(String htmlString) { Document graphDoc = Jsoup.parse(htmlString); Element htmlNode = graphDoc.getElementsByTag("html").get(0); htmlNode.attr("style", "height: 100%"); Element bodyNode = graphDoc.getElementsByTag("body").get(0); bodyNode.attr("style", "height: 90%; margin:0;"); return graphDoc.html(); } public boolean isGraphDetailField() { return "graph".equals(fieldForm); } public boolean isPrintSupported() { return !"".equals(valueString); } }