/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.web.dcui; import java.io.IOException; import java.io.PrintStream; import divconq.lang.op.OperationCallback; import divconq.util.StringUtil; import divconq.web.IOutputAdapter; import divconq.web.WebContext; import divconq.xml.XElement; public class ViewBuilder implements IViewBuilder { protected boolean dynamic = false; protected Fragment frag = null; @Override public void execute(WebContext ctx, IOutputAdapter adapt) throws Exception { //System.out.println("a " + System.currentTimeMillis()); String mode = ctx.getExternalParam("_dcui"); if ("dyn".equals(mode) || "dyn".equals(mode)) this.dynamic = true; this.frag = new Fragment(); if (this.dynamic) { this.frag.initializePart(ctx, adapt, new OperationCallback() { @Override public void callback() { String pclass = ViewBuilder.this.frag.source.getAttribute("PageClass"); XElement skel = ViewBuilder.this.frag.source.find("Skeleton"); String sclass = skel.getAttribute("class"); String fclass = ""; if (StringUtil.isNotEmpty(pclass)) fclass += pclass + " "; if (StringUtil.isNotEmpty(sclass)) fclass += sclass + " "; ViewBuilder.this.frag.addArgs(new Attributes("class", fclass)); ViewBuilder.this.doBuild(ctx); } }); } else { this.frag.initializeRoot(ctx, adapt, new OperationCallback() { @Override public void callback() { ViewBuilder.this.doBuild(ctx); } }); } } public void doBuild(WebContext ctx) { ctx.setServerScript(this.frag.getServerScript()); XElement src = ViewBuilder.this.frag.getSource(); ctx.putInternalParam("PageTitle", ctx.expandMacros(src.getAttribute("Title"))); this.frag.doBuild(ctx); this.frag.awaitForFutures(new OperationCallback() { @Override public void callback() { try { ViewBuilder.this.doWrite(ctx); } catch (Exception x) { // TODO System.out.println("View builder build error: " + x); } } }); } public void doWrite(WebContext ctx) throws IOException { XElement src = this.frag.getSource(); if (this.dynamic) { ctx.getResponse().setHeader("Content-Type", "application/javascript"); PrintStream ps = ctx.getResponse().getPrintStream(); ps.println("dc.pui.Loader.addPageDefinition('" + ctx.getRequest().getOriginalPath() + "', {"); if (src.hasAttribute("Title")) { String title = ctx.getInternalParam("PageTitle"); // ctx.expandMacros(src.getAttribute("Title")); ps.print("\tTitle: '"); Node.writeDynamicJsString(ps, title); ps.println("',"); } if (this.frag.hasAttribute("class")) { String pclass = this.frag.getAttribute("class"); ps.print("\tPageClass: '"); Node.writeDynamicJsString(ps, pclass); ps.println("',"); } ps.println("\tLayout: ["); this.frag.writeDynamicChildren(ps, ""); ps.println(); ps.println("\t],"); // ============================================== // Styles // ============================================== boolean first = true; ps.print("\tRequireStyles: ["); for (XElement func : src.selectAll("RequireStyle")) { if (!func.hasAttribute("Path")) continue; if (first) first = false; else ps.print(","); ps.print(" '"); Node.writeDynamicJsString(ps, func.getAttribute("Path")); ps.print("'"); } ps.println(" ], "); // ============================================== // Require Types // ============================================== first = true; ps.print("\tRequireType: ["); for (XElement func : src.selectAll("Require")) { if (!func.hasAttribute("Types")) continue; if (first) first = false; else ps.print(","); ps.print(" '"); Node.writeDynamicJsString(ps, func.getAttribute("Types")); ps.print("'"); } ps.println(" ], "); // ============================================== // Require Tr // ============================================== first = true; ps.print("\tRequireTr: ["); for (XElement func : src.selectAll("Require")) { if (!func.hasAttribute("Trs")) continue; if (first) first = false; else ps.print(","); ps.print(" '"); Node.writeDynamicJsString(ps, func.getAttribute("Trs")); ps.print("'"); } ps.println(" ], "); // ============================================== // Libs // ============================================== first = true; ps.print("\tRequireLibs: ["); for (XElement func : src.selectAll("RequireLib")) { if (!func.hasAttribute("Path")) continue; if (first) first = false; else ps.print(","); ps.print(" '"); Node.writeDynamicJsString(ps, func.getAttribute("Path")); ps.print("'"); } ps.println(" ], "); // ============================================== // Functions // ============================================== first = true; ps.println("\tFunctions: {"); for (XElement func : src.selectAll("Function")) { if (!func.hasAttribute("Name")) continue; if (first) first = false; else ps.println(","); ps.print("\t\t" + func.getAttribute("Name") + ": function(" + func.getAttribute("Params", "") + ") { \n"); ps.print(func.getText()); ps.print("\n\t\t}"); } ps.println(); ps.println("\t}, "); // ============================================== // Load Functions // ============================================== first = true; ps.println("\tLoadFunctions: ["); for (XElement func : src.selectAll("Function")) { if (!"Load".equals(func.getAttribute("Mode"))) continue; if (first) first = false; else ps.println(","); if (func.hasAttribute("Name")) { ps.print(" '"); Node.writeDynamicJsString(ps, func.getAttribute("Name")); ps.print("'"); } else { ps.print("\t\t function(" + func.getAttribute("Params", "") + ") {"); ps.print("\t\t\t // func " + func.getAttribute("Name") + "\n"); ps.print(func.getText()); ps.print("\n\t\t}"); } } ps.println(); ps.println("\t]"); ps.println("});"); ps.println(); ps.println("dc.pui.Loader.resumePageLoad();"); } else { ctx.getResponse().setHeader("Content-Type", "text/html; charset=utf-8"); ctx.getResponse().setHeader("X-UA-Compatible", "IE=Edge,chrome=1"); ctx.getResponse().getPrintStream().println("<!DOCTYPE html>"); this.frag.write(ctx); } ctx.send(); //System.out.println("b " + System.currentTimeMillis()); } /* public static String streamNodes(String indent, List<Node> children, boolean cleanWhitespace) { if (children.size() == 0) return null; ByteArrayOutputStream os = new ByteArrayOutputStream(); PrintStream out = new PrintStream(os); boolean lastblock = true; boolean firstch = true; for (Node node : children) { node.stream(out, indent, (firstch || lastblock), true); lastblock = node.getBlockIndent(); firstch = false; } out.flush(); if (cleanWhitespace) return StringUtil.stripWhitespacePerXml(os.toString()); return os.toString(); } */ }