From b57acbb87f2d4422cd16851239e29418c231f90d Mon Sep 17 00:00:00 2001 From: ryounes Date: Thu, 7 Apr 2011 16:15:49 +0000 Subject: [PATCH] NIHVIVO-1562 Add initial work on new dump package for freemarker, including unit tests. --- .../ext/dump/BaseDumpDirective.java | 179 +++++++++++++++ .../freemarker/ext/dump/DumpDirective.java | 50 +++++ .../ext/dump/DumpDirectiveTest.java | 209 ++++++++++++++++++ 3 files changed, 438 insertions(+) create mode 100644 webapp/src/freemarker/ext/dump/BaseDumpDirective.java create mode 100644 webapp/src/freemarker/ext/dump/DumpDirective.java create mode 100644 webapp/test/freemarker/ext/dump/DumpDirectiveTest.java diff --git a/webapp/src/freemarker/ext/dump/BaseDumpDirective.java b/webapp/src/freemarker/ext/dump/BaseDumpDirective.java new file mode 100644 index 000000000..120e39187 --- /dev/null +++ b/webapp/src/freemarker/ext/dump/BaseDumpDirective.java @@ -0,0 +1,179 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package freemarker.ext.dump; + +import java.io.IOException; +import java.io.StringWriter; +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 freemarker.core.Environment; +import freemarker.template.Template; +import freemarker.template.TemplateBooleanModel; +import freemarker.template.TemplateDateModel; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateHashModel; +import freemarker.template.TemplateHashModelEx; +import freemarker.template.TemplateMethodModel; +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; + +/* TODO + * - Check error messages generated for TemplateModelException-s. If too generic, need to catch, create specific + * error message, and rethrow. + */ + +public abstract class BaseDumpDirective implements TemplateDirectiveModel { + + private static final Log log = LogFactory.getLog(BaseDumpDirective.class); + + protected Map getTemplateVariableData(String varName, Environment env) + throws TemplateModelException { + + Map map = new HashMap(); + map.put("name", varName); + + TemplateHashModel dataModel = env.getDataModel(); + TemplateModel model = dataModel.get(varName); + map.putAll(getData(model)); + + return map; + } + + private Map getData(TemplateModel model) throws TemplateModelException { + Map map = new HashMap(); + + // Don't return null if model == null. We still want to send the map to the template. + if (model != null) { + // Do TemplateHashModel case first, because model of POJOs are + // StringModels, which are both TemplateScalarModels and TemplateHashModels. + if (model instanceof TemplateHashModel) { + map.putAll( getTemplateModelData( ( TemplateHashModel)model ) ); + + } else if (model instanceof TemplateScalarModel) { + map.putAll( getTemplateModelData( (TemplateScalarModel)model ) ); + + } else if (model instanceof TemplateBooleanModel) { + map.putAll( getTemplateModelData( (TemplateBooleanModel)model ) ); + + } else if (model instanceof TemplateNumberModel) { + map.putAll( getTemplateModelData( (TemplateNumberModel)model ) ); + + } else if (model instanceof TemplateDateModel) { + map.putAll( getTemplateModelData( (TemplateDateModel)model ) ); + + } else if (model instanceof TemplateSequenceModel){ + map.putAll( getTemplateModelData( ( TemplateSequenceModel)model ) ); + + } else if (model instanceof TemplateHashModelEx) { + map.putAll( getTemplateModelData( ( TemplateHashModelEx)model ) ); + + } else if (model instanceof TemplateMethodModel) { + map.putAll( getTemplateModelData( ( TemplateMethodModel)model ) ); + + } else if (model instanceof TemplateDirectiveModel) { + map.putAll( getTemplateModelData( ( TemplateDirectiveModel)model ) ); + + } else { + map.putAll( getTemplateModelData( (TemplateModel)model ) ); + } + } + + return map; + } + + private Map getTemplateModelData(TemplateScalarModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "String"); + map.put("value", model.getAsString()); + return map; + } + + private Map getTemplateModelData(TemplateBooleanModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Boolean"); + map.put("value", model.getAsBoolean()); + return map; + } + + private Map getTemplateModelData(TemplateNumberModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Number"); + map.put("value", model.getAsNumber()); + return map; + } + + private Map getTemplateModelData(TemplateDateModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Date"); + map.put("dateType", model.getDateType()); + map.put("value", model.getAsDate()); + return map; + } + + private Map getTemplateModelData(TemplateHashModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Hash"); + //map.put("value", model.getAsBoolean()); + return map; + } + + private Map getTemplateModelData(TemplateSequenceModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Sequence"); + //map.put("value", model.getAsNumber()); + return map; + } + + private Map getTemplateModelData(TemplateHashModelEx model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "HashModelEx");; + //map.put("value", model.getAsDate()); + return map; + } + + private Map getTemplateModelData(TemplateMethodModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Method"); + //map.put("value", model.getAsNumber()); + return map; + } + + private Map getTemplateModelData(TemplateDirectiveModel model) throws TemplateModelException { + Map map = new HashMap(); + map.put("type", "Directive");; + //map.put("value", model.getAsDate()); + return map; + } + + private Map getTemplateModelData(TemplateModel model) throws TemplateModelException { + // One of the above cases should have applied. Track whether this actually occurs. + log.debug("Found model with no known type"); // + Map map = new HashMap(); + Object unwrappedModel = DeepUnwrap.permissiveUnwrap(model); + map.put("type", unwrappedModel.getClass().getName()); + map.put("value", unwrappedModel.toString()); + return map; + } + + protected void dump(String templateName, Map map, String modelName, Environment env) + throws TemplateException, IOException { + + Template template = env.getConfiguration().getTemplate(templateName); + StringWriter sw = new StringWriter(); + template.process(map, sw); + Writer out = env.getOut(); + out.write(sw.toString()); + + } + +} diff --git a/webapp/src/freemarker/ext/dump/DumpDirective.java b/webapp/src/freemarker/ext/dump/DumpDirective.java new file mode 100644 index 000000000..8a3730868 --- /dev/null +++ b/webapp/src/freemarker/ext/dump/DumpDirective.java @@ -0,0 +1,50 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package freemarker.ext.dump; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import freemarker.core.Environment; +import freemarker.template.SimpleScalar; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; + +public class DumpDirective extends BaseDumpDirective { + + @SuppressWarnings("unused") + private static final Log log = LogFactory.getLog(DumpDirective.class); + + @SuppressWarnings("rawtypes") + @Override + public void execute(Environment env, Map params, TemplateModel[] loopVars, + TemplateDirectiveBody body) throws TemplateException, IOException { + + if (loopVars.length != 0) { + throw new TemplateModelException( + "The dump directive doesn't allow loop variables."); + } + if (body != null) { + throw new TemplateModelException( + "The dump directive doesn't allow nested content."); + } + + Object o = params.get("var"); + if ( !(o instanceof SimpleScalar)) { + throw new TemplateModelException( + "Value of parameter 'var' must be a string."); + } + + String varName = ((SimpleScalar)o).getAsString(); + Map map = new HashMap(); + map.put("var", getTemplateVariableData(varName, env)); + + dump("dumpvar.ftl", map, varName, env); + } +} diff --git a/webapp/test/freemarker/ext/dump/DumpDirectiveTest.java b/webapp/test/freemarker/ext/dump/DumpDirectiveTest.java new file mode 100644 index 000000000..b981ec8a6 --- /dev/null +++ b/webapp/test/freemarker/ext/dump/DumpDirectiveTest.java @@ -0,0 +1,209 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package freemarker.ext.dump; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import freemarker.core.Environment; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateDirectiveBody; +import freemarker.template.TemplateDirectiveModel; +import freemarker.template.TemplateException; +import freemarker.template.TemplateMethodModel; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; + +public class DumpDirectiveTest { + + private Template template; + + @Before + public void setUp() { + Configuration config = new Configuration(); + String templateStr = ""; + try { + template = new Template("template", new StringReader(templateStr), config); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void dumpString() { + + String varName = "dog"; + String value = "Rover"; + Map dataModel = new HashMap(); + dataModel.put(varName, value); + + Map expected = new HashMap(); + expected.put("name", varName); + expected.put("type", "String"); + expected.put("value", value); + + try { + Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); + Map dumpData = new DumpDirective().getTemplateVariableData(varName, env); + Assert.assertEquals(expected, dumpData); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void dumpBoolean() { + + String varName = "hasSiteAdminAccess"; + boolean value = true; + Map dataModel = new HashMap(); + dataModel.put(varName, value); + + Map expected = new HashMap(); + expected.put("name", varName); + expected.put("type", "Boolean"); + expected.put("value", value); + + try { + Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); + Map dumpData = new DumpDirective().getTemplateVariableData(varName, env); + Assert.assertEquals(expected, dumpData); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void dumpNumber() { + + String varName = "tabCount"; + int value = 7; + Map dataModel = new HashMap(); + dataModel.put(varName, value); + + Map expected = new HashMap(); + expected.put("name", varName); + expected.put("type", "Number"); + expected.put("value", value); + + try { + Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); + Map dumpData = new DumpDirective().getTemplateVariableData(varName, env); + Assert.assertEquals(expected, dumpData); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void dumpDate() { + + String varName = "tabCount"; + int value = 7; + Map dataModel = new HashMap(); + dataModel.put(varName, value); + + Map expected = new HashMap(); + expected.put("name", varName); + expected.put("type", "Number"); + expected.put("value", value); + + try { + Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); + Map dumpData = new DumpDirective().getTemplateVariableData(varName, env); + Assert.assertEquals(expected, dumpData); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + // RY test method and directive types with and without help methods + + @Test + public void dumpMethod() { + + String varName = "profileUri"; + TemplateMethodModel value = new StubMethodModel(); + Map dataModel = new HashMap(); + dataModel.put(varName, value); + + Map expected = new HashMap(); + expected.put("name", varName); + expected.put("type", "Method"); + //expected.put("value", value); + + try { + Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); + Map dumpData = new DumpDirective().getTemplateVariableData(varName, env); + Assert.assertEquals(expected, dumpData); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + @Test + public void dumpDirective() { + + String varName = "widget"; + TemplateDirectiveModel value = new StubDirectiveModel(); + Map dataModel = new HashMap(); + dataModel.put(varName, value); + + Map expected = new HashMap(); + expected.put("name", varName); + expected.put("type", "Directive"); + //expected.put("value", value); + + try { + Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); + Map dumpData = new DumpDirective().getTemplateVariableData(varName, env); + Assert.assertEquals(expected, dumpData); + } catch (Exception e) { + Assert.fail(e.getMessage()); + } + } + + // RY Do these with different BeansWrappers + @Test + public void dumpSequence() { + + } + + @Test + public void dumpHash() { + + } + + @Test + public void dumpHashEx() { + + } + + private class StubMethodModel implements TemplateMethodModel { + + @Override + public Object exec(List arg0) throws TemplateModelException { + return null; + } + } + + private class StubDirectiveModel implements TemplateDirectiveModel { + + @Override + public void execute(Environment arg0, Map arg1, TemplateModel[] arg2, + TemplateDirectiveBody arg3) throws TemplateException, + IOException { + + } + + } +}