NIHVIVO-564 Rearchitected dump directives to use shared helper methods rather than having dumpAll template call dump directive.

This commit is contained in:
rjy7 2010-08-05 19:25:12 +00:00
parent d3b8b89de4
commit 91468db876
10 changed files with 194 additions and 125 deletions

View file

@ -282,8 +282,8 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// Add any Java directives the templates should have access to // Add any Java directives the templates should have access to
private void addDirectives(Map<String, Object> map) { private void addDirectives(Map<String, Object> map) {
map.put("dump", new edu.cornell.mannlib.vitro.webapp.web.directives.DumpDirective()); map.put("dump", new edu.cornell.mannlib.vitro.webapp.web.directives.dump.DumpDirective());
map.put("dumpAll", new edu.cornell.mannlib.vitro.webapp.web.directives.DumpAllDirective()); map.put("dumpAll", new edu.cornell.mannlib.vitro.webapp.web.directives.dump.DumpAllDirective());
} }
// Add variables that should be available only to the page's root map, not to the body. // Add variables that should be available only to the page's root map, not to the body.

View file

@ -7,12 +7,18 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper;
import edu.cornell.mannlib.vitro.webapp.web.directives.dump.DumpDirective;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateDirectiveModel;
public abstract class BaseTemplateDirectiveModel implements TemplateDirectiveModel { public abstract class BaseTemplateDirectiveModel implements TemplateDirectiveModel {
private static final Log log = LogFactory.getLog(BaseTemplateDirectiveModel.class);
public String help(Configuration config) { public String help(Configuration config) {
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();

View file

@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.directives; package edu.cornell.mannlib.vitro.webapp.web.directives.dump;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
@ -14,6 +14,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper;
import edu.cornell.mannlib.vitro.webapp.web.directives.BaseTemplateDirectiveModel;
import freemarker.core.Environment; import freemarker.core.Environment;
import freemarker.template.Configuration; import freemarker.template.Configuration;
@ -47,45 +48,38 @@ public class DumpAllDirective extends BaseTemplateDirectiveModel {
"The dumpAll directive doesn't allow nested content."); "The dumpAll directive doesn't allow nested content.");
} }
Configuration config = env.getConfiguration();
TemplateHashModel dataModel = env.getDataModel(); TemplateHashModel dataModel = env.getDataModel();
Map<String, Object> models = new HashMap<String, Object>();
Map<String, String> directives = new HashMap<String, String>();
Map<String, Object> dm = (Map<String, Object>) DeepUnwrap.permissiveUnwrap(dataModel); Map<String, Object> dm = (Map<String, Object>) DeepUnwrap.permissiveUnwrap(dataModel);
List<String> varNames = new ArrayList(dm.keySet()); List<String> varNames = new ArrayList(dm.keySet());
Collections.sort(varNames); Collections.sort(varNames);
DumpHelper helper = new DumpHelper(env);
Configuration config = env.getConfiguration();
List<String> models = new ArrayList<String>();
List<String> directives = new ArrayList<String>();
for (String var : varNames) { for (String var : varNames) {
// RY Instead, push each var/directive through the template and return a string.
// The meat of dumpDirective will go in a helper.
// Send the two lists of strings (variables and directives) to dump-datamodel.ftl.
// That way, the directive dump won't be broken up into two pieces, for example.
Object value = dm.get(var); Object value = dm.get(var);
if (value instanceof BaseTemplateDirectiveModel) { if (value instanceof BaseTemplateDirectiveModel) {
String help = ((BaseTemplateDirectiveModel) value).help(config); String help = ((BaseTemplateDirectiveModel) value).help(config);
directives.put(var, help); directives.add(help);
} else { } else {
models.put(var, value); models.add(helper.getVariableDump(var));
} }
} }
String templateName = "dump-all.ftl";
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();
map.put("models", models); map.put("models", models);
map.put("directives", directives); map.put("directives", directives);
map.put("stylesheets", dataModel.get("stylesheets"));
map.put("dump", dataModel.get("dump"));
// Put the current datamodel into the new datamodel so its values can be dumped with the dump directive
// RY Another way to do this would be to loop through the data model here, merging each variable with
// the dump-var.ftl template and adding it to the output string.
map.put("datamodel", dataModel);
map.put("containingTemplate", env.getTemplate().getName()); map.put("containingTemplate", env.getTemplate().getName());
FreemarkerHelper helper = new FreemarkerHelper(config); try {
String output = helper.mergeMapToTemplate(templateName, map); map.put("stylesheets", dataModel.get("stylesheets"));
Writer out = env.getOut(); } catch (TemplateModelException e) {
out.write(output); log.error("Error getting value of stylesheets variable from data model.");
}
helper.writeDump("dumpAll.ftl", map, "template data model");
} }

View file

@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.directives; package edu.cornell.mannlib.vitro.webapp.web.directives.dump;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
@ -13,6 +13,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper;
import edu.cornell.mannlib.vitro.webapp.web.directives.BaseTemplateDirectiveModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
import freemarker.core.Environment; import freemarker.core.Environment;
import freemarker.template.Configuration; import freemarker.template.Configuration;
@ -52,76 +53,23 @@ public class DumpDirective extends BaseTemplateDirectiveModel {
throw new TemplateModelException( throw new TemplateModelException(
"Value of parameter 'var' must be a string."); "Value of parameter 'var' must be a string.");
} }
String var = ((SimpleScalar)o).getAsString();
Object r = params.get("dataModelDump"); String var = ((SimpleScalar)o).getAsString();
boolean dataModelDump = false; DumpHelper helper = new DumpHelper(env);
if (r != null) { Map<String, Object> map = helper.getVariableDumpData(var);
if ( !(r instanceof TemplateBooleanModel)) { map.put("var", helper.getVariableDump(var));
throw new TemplateModelException(
"Value of parameter 'recursive' must be a boolean: true or false without quotation marks.");
}
dataModelDump = ((TemplateBooleanModel) r).getAsBoolean();
}
TemplateHashModel dataModel = env.getDataModel(); TemplateHashModel dataModel = env.getDataModel();
if (dataModelDump) {
dataModel = (TemplateHashModel) dataModel.get("datamodel");
}
TemplateModel val = null;
try { try {
val = dataModel.get(var);
} catch (TemplateModelException tme) {
log.error("Error getting value of template model " + var + " from data model.");
}
// Just use this for now. Handles nested collections.
String value = val.toString();
String type = null;
Object unwrappedModel = DeepUnwrap.permissiveUnwrap(val);
// This case must precede the TemplateScalarModel case, because
// val is an instance of StringModel.
if (unwrappedModel instanceof BaseTemplateModel) {
type = unwrappedModel.getClass().getName();
value = ((BaseTemplateModel)unwrappedModel).dump();
} else if (val instanceof TemplateScalarModel) {
type = "string";
} else if (val instanceof TemplateDateModel) {
type = "date";
} else if (val instanceof TemplateNumberModel) {
type = "number";
} else if (val instanceof TemplateBooleanModel) {
value = ((TemplateBooleanModel) val).getAsBoolean() ? "true" : "false";
type = "boolean";
} else if (val instanceof TemplateSequenceModel){
type = "sequence";
} else if (val instanceof TemplateHashModel) {
type = "hash";
// In recursive dump, we've gotten down to a raw string. Just output it.
// } else if (val == null) {
// out.write(var);
// return;
// Add a case for BaseTemplateModel - our template model objects will have a dump() method.
} else {
type = "object";
}
Map<String, Object> map = new HashMap<String, Object>();
map.put("var", var);
map.put("value", value);
map.put("type", type);
map.put("stylesheets", dataModel.get("stylesheets")); map.put("stylesheets", dataModel.get("stylesheets"));
//map.put("dump", this); // would need for recursive calls } catch (TemplateModelException e) {
log.error("Error getting value of stylesheets variable from data model.");
String output = new FreemarkerHelper(env.getConfiguration()).mergeMapToTemplate("dump-var.ftl", map);
Writer out = env.getOut();
out.write(output);
} }
helper.writeDump("dump.ftl", map, var);
}
public String help(Configuration config) { public String help(Configuration config) {
Map<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>();

View file

@ -0,0 +1,111 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.directives.dump;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerHelper;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
import freemarker.core.Environment;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateDateModel;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.TemplateScalarModel;
import freemarker.template.TemplateSequenceModel;
import freemarker.template.utility.DeepUnwrap;
public class DumpHelper {
private static final Log log = LogFactory.getLog(DumpHelper.class);
private Environment environment = null;
public DumpHelper(Environment env) {
environment = env;
}
public String getVariableDump(String varName) {
Map<String, Object> map = getVariableDumpData(varName);
return new FreemarkerHelper(environment.getConfiguration()).mergeMapToTemplate("dump-var.ftl", map);
}
public Map<String, Object> getVariableDumpData(String varName) {
TemplateHashModel dataModel = environment.getDataModel();
TemplateModel tm = null;
try {
tm = dataModel.get(varName);
} catch (TemplateModelException tme) {
log.error("Error getting value of template model " + varName + " from data model.");
}
// Just use toString() method for now. Handles nested collections. Could make more sophisticated later.
String value = tm.toString();
String type = null;
Object unwrappedModel = null;
try {
unwrappedModel = DeepUnwrap.permissiveUnwrap(tm);
} catch (TemplateModelException e) {
log.error("Cannot unwrap template model " + varName + ".");
}
// This case must precede the TemplateScalarModel case, because
// tm is an instance of StringModel.
if (unwrappedModel instanceof BaseTemplateModel) {
type = unwrappedModel.getClass().getName();
value = ((BaseTemplateModel)unwrappedModel).dump();
} else if (tm instanceof TemplateScalarModel) {
type = "string";
} else if (tm instanceof TemplateDateModel) {
type = "date";
} else if (tm instanceof TemplateNumberModel) {
type = "number";
} else if (tm instanceof TemplateBooleanModel) {
type = "boolean";
try {
value = ((TemplateBooleanModel) tm).getAsBoolean() ? "true" : "false";
} catch (TemplateModelException e) {
log.error("Error getting boolean value for " + varName + ".");
}
} else if (tm instanceof TemplateSequenceModel){
type = "sequence";
} else if (tm instanceof TemplateHashModel) {
type = "hash";
// In recursive dump, we've gotten down to a raw string. Just output it.
// } else if (val == null) {
// out.write(var);
// return;
} else {
type = "object";
}
Map<String, Object> map = new HashMap<String, Object>();
map.put("var", varName);
map.put("value", value);
map.put("type", type);
return map;
}
public void writeDump(String templateName, Map<String, Object> map, String modelName) {
FreemarkerHelper helper = new FreemarkerHelper(environment.getConfiguration());
String output = helper.mergeMapToTemplate(templateName, map);
Writer out = environment.getOut();
try {
out.write(output);
} catch (IOException e) {
log.error("Error writing dump of " + modelName + ".");
}
}
}

View file

@ -1,25 +0,0 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for dumping the template data model -->
<div class="dump datamodel">
<h3>Data Model Dump for Template <em>${containingTemplate}</em></h3>
<h4>VARIABLES</h4>
<ul>
<#list models?keys as key>
<li><@dump var="${key}" dataModelDump=true /></li>
</#list>
</ul>
<h4>DIRECTIVES</h4>
<ul>
<#list directives?keys as directive>
<li>${directives[directive]}</li>
</#list>
</ul>
</div>

View file

@ -4,11 +4,9 @@
<div class="dump"> <div class="dump">
<h6>Dump of template variable <em>${var}</em>:</h6> <h6>Variable name: <em>${var}</em></h6>
<strong>Type:</strong> ${type}<br /> <strong>Type:</strong> ${type}<br />
<strong>Value:</strong> ${value}<br /> <strong>Value:</strong> ${value}<br />
</div> </div>
${stylesheets.add("/css/dump.css")}

View file

@ -0,0 +1,9 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for dump directive -->
<h3>Template variable dump</h3>
${var}
${stylesheets.add("/css/dump.css")}

View file

@ -0,0 +1,27 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for dumpAll directive (dumping template data model) -->
<div class="dump datamodel">
<h3>Data model dump for template <em>${containingTemplate}</em></h3>
<h4>VARIABLES</h4>
<ul>
<#list models as model>
<li>${model}</li>
</#list>
</ul>
<h4>DIRECTIVES</h4>
<ul>
<#list directives as directive>
<li>${directive}</li>
</#list>
</ul>
</div>
${stylesheets.add("/css/dump.css")}

View file

@ -46,17 +46,18 @@
<p><strong>Berries: </strong>${berries}</p> <p><strong>Berries: </strong>${berries}</p>
<#--
<@dump var="now" /> <@dump var="now" />
<@dump var="urls" /> <@dump var="urls" />
<@dump var="fruit" /> <@dump var="fruit" />
<@dump var="trueStatement" /> <@dump var="trueStatement" />
<@dump var="falseStatement" /> <@dump var="falseStatement" />
<@dump var="zoo1" /> <@dump var="zoo1" />
-->
${stylesheets.addFromTheme("/sstest.css", "/sstest2.css")} ${stylesheets.addFromTheme("/sstest.css", "/sstest2.css")}
${scripts.addFromTheme("/jstest.js")} ${scripts.addFromTheme("/jstest.js")}
${scripts.add("/js/script1.js", "/js/script2.js", "/js/script3.js")} ${scripts.add("/js/script1.js", "/js/script2.js", "/js/script3.js")}
<@dumpAll /> <@dumpAll />