/* $This file is distributed under the terms of the license in /doc/license.txt$ */ package freemarker.ext.dump; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import org.apache.commons.lang.time.DateUtils; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; import freemarker.core.Environment; import freemarker.ext.beans.BeansWrapper; import freemarker.ext.dump.BaseDumpDirective.DateType; import freemarker.ext.dump.BaseDumpDirective.Key; import freemarker.ext.dump.BaseDumpDirective.Value; import freemarker.ext.dump.BaseDumpDirective.Type; import freemarker.template.Configuration; import freemarker.template.SimpleCollection; import freemarker.template.Template; import freemarker.template.TemplateCollectionModel; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateMethodModel; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; /** * Unit tests of dump directive. The tests follow the same basic pattern: * 1. Create the data model * 2. Create the expected dump data structure * 3. Create the actual dump data structure by running the data model through a processing environment * 4. Compare expected and actual dump data structures * * @author rjy7 * */ 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) { fail(e.getMessage()); } // Turn off log messages to console Logger.getLogger(BaseDumpDirective.class).setLevel(Level.OFF); } @Test public void dumpUndefinedValue() { String varName = "dog"; Map dataModel = new HashMap(); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.VALUE.toString(), Value.UNDEFINED); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpString() { String varName = "dog"; Map dataModel = new HashMap(); String value = "Rover"; dataModel.put(varName, value); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.STRING); expectedDumpValue.put(Key.VALUE.toString(), value); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpBoolean() { String varName = "isLoggedIn"; Map dataModel = new HashMap(); boolean value = true; dataModel.put(varName, value); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.BOOLEAN); expectedDumpValue.put(Key.VALUE.toString(), value); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpNumber() { String varName = "tabCount"; Map dataModel = new HashMap(); int value = 7; dataModel.put(varName, value); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.NUMBER); expectedDumpValue.put(Key.VALUE.toString(), value); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpSimpleDate() { String varName = "now"; Map dataModel = new HashMap(); Date now = new Date(); dataModel.put(varName, now); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DATE); expectedDumpValue.put(Key.DATE_TYPE.toString(), DateType.UNKNOWN); expectedDumpValue.put(Key.VALUE.toString(), now); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpCalendarDate() { String varName = "myDate"; Map dataModel = new HashMap(); Calendar c = Calendar.getInstance(); c.set(1991, Calendar.MAY, 5); Date myDate = c.getTime(); dataModel.put("myDate", myDate); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DATE); expectedDumpValue.put(Key.DATE_TYPE.toString(), DateType.UNKNOWN); expectedDumpValue.put(Key.VALUE.toString(), myDate); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpDateTime() { String varName = "timestamp"; Map dataModel = new HashMap(); Timestamp ts = new Timestamp(1302297332043L); dataModel.put(varName, ts); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DATE); expectedDumpValue.put(Key.DATE_TYPE.toString(), DateType.DATETIME); expectedDumpValue.put(Key.VALUE.toString(), ts); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpSqlDate() { String varName = "date"; Map dataModel = new HashMap(); java.sql.Date date = new java.sql.Date(1302297332043L); dataModel.put(varName, date); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DATE); expectedDumpValue.put(Key.DATE_TYPE.toString(), DateType.DATE); expectedDumpValue.put(Key.VALUE.toString(), date); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpTime() { String varName = "time"; Map dataModel = new HashMap(); Time time = new Time(1302297332043L); dataModel.put(varName, time); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DATE); expectedDumpValue.put(Key.DATE_TYPE.toString(), DateType.TIME); expectedDumpValue.put(Key.VALUE.toString(), time); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpHelplessMethod() { String varName = "square"; Map dataModel = new HashMap(); TemplateMethodModel methodModel = new HelplessMethod(); dataModel.put(varName, methodModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.METHOD); expectedDumpValue.put(Key.CLASS.toString(), methodModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), null); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpHelpfulMethod() { String varName = "square"; Map dataModel = new HashMap(); TemplateMethodModel methodModel = new HelpfulMethod(); dataModel.put(varName, methodModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.METHOD); expectedDumpValue.put(Key.CLASS.toString(), methodModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), getMethodHelp(varName)); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpMethodWithStringHelp() { String varName = "square"; Map dataModel = new HashMap(); TemplateMethodModel methodModel = new MethodWithStringHelp(); dataModel.put(varName, methodModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.METHOD); expectedDumpValue.put(Key.CLASS.toString(), methodModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), null); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpMethodWithStringStringMapHelp() { String varName = "square"; Map dataModel = new HashMap(); TemplateMethodModel methodModel = new MethodWithStringStringMapHelp(); dataModel.put(varName, methodModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.METHOD); expectedDumpValue.put(Key.CLASS.toString(), methodModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), new HashMap()); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpHelplessDirective() { String varName = "dump"; Map dataModel = new HashMap(); TemplateDirectiveModel directiveModel = new HelplessDirective(); dataModel.put(varName, directiveModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DIRECTIVE); expectedDumpValue.put(Key.CLASS.toString(), directiveModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), null); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpHelpfulDirective() { String varName = "dump"; Map dataModel = new HashMap(); TemplateDirectiveModel directiveModel = new HelpfulDirective(); dataModel.put(varName, directiveModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DIRECTIVE); expectedDumpValue.put(Key.CLASS.toString(), directiveModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), getDirectiveHelp(varName)); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpDirectiveWithStringHelp() { String varName = "dump"; Map dataModel = new HashMap(); TemplateDirectiveModel directiveModel = new DirectiveWithStringHelp(); dataModel.put(varName, directiveModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DIRECTIVE); expectedDumpValue.put(Key.CLASS.toString(), directiveModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), null); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpDirectiveWithStringStringMapHelp() { String varName = "dump"; Map dataModel = new HashMap(); TemplateDirectiveModel directiveModel = new DirectiveWithStringStringMapHelp(); dataModel.put(varName, directiveModel); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.DIRECTIVE); expectedDumpValue.put(Key.CLASS.toString(), directiveModel.getClass().getName()); expectedDumpValue.put(Key.HELP.toString(), new HashMap()); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpStringList() { String varName = "fruit"; Map dataModel = new HashMap(); List myList = new ArrayList(); myList.add("apples"); myList.add("bananas"); myList.add("oranges"); dataModel.put(varName, myList); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.SEQUENCE); List> myListItemsExpectedDump = new ArrayList>(myList.size()); for ( String str : myList) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.STRING); itemDump.put(Key.VALUE.toString(), str); myListItemsExpectedDump.add(itemDump); } expectedDumpValue.put(Key.VALUE.toString(), myListItemsExpectedDump); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpStringArray() { String varName = "fruit"; Map dataModel = new HashMap(); String[] myArray = { "apples", "bananas", "oranges" }; dataModel.put(varName, myArray); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.SEQUENCE); List> myArrayexpectedDumpValue = new ArrayList>(myArray.length); for ( String str : myArray) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.STRING); itemDump.put(Key.VALUE.toString(), str); myArrayexpectedDumpValue.add(itemDump); } expectedDumpValue.put(Key.VALUE.toString(), myArrayexpectedDumpValue); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpMixedList() { String varName = "stuff"; Map dataModel = new HashMap(); List mixedList = new ArrayList(); String myString = "apples"; mixedList.add(myString); int myInt = 4; mixedList.add(myInt); boolean myBool = true; mixedList.add(myBool); List myList = new ArrayList(); myList.add("dog"); myList.add("cat"); myList.add("elephant"); mixedList.add(myList); dataModel.put(varName, mixedList); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.SEQUENCE); List> mixedListexpectedDumpValue = new ArrayList>(mixedList.size()); Map myStringexpectedDumpValue = new HashMap(); myStringexpectedDumpValue.put(Key.TYPE.toString(), Type.STRING); myStringexpectedDumpValue.put(Key.VALUE.toString(), myString); mixedListexpectedDumpValue.add(myStringexpectedDumpValue); Map myIntexpectedDumpValue = new HashMap(); myIntexpectedDumpValue.put(Key.TYPE.toString(), Type.NUMBER); myIntexpectedDumpValue.put(Key.VALUE.toString(), myInt); mixedListexpectedDumpValue.add(myIntexpectedDumpValue); Map myBoolexpectedDumpValue = new HashMap(); myBoolexpectedDumpValue.put(Key.TYPE.toString(), Type.BOOLEAN); myBoolexpectedDumpValue.put(Key.VALUE.toString(), myBool); mixedListexpectedDumpValue.add(myBoolexpectedDumpValue); Map myListexpectedDumpValue = new HashMap(); myListexpectedDumpValue.put(Key.TYPE.toString(), Type.SEQUENCE); List> myListItemsexpectedDumpValue = new ArrayList>(myList.size()); for ( String animal : myList ) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.STRING); itemDump.put(Key.VALUE.toString(), animal); myListItemsexpectedDumpValue.add(itemDump); } myListexpectedDumpValue.put(Key.VALUE.toString(), myListItemsexpectedDumpValue); mixedListexpectedDumpValue.add(myListexpectedDumpValue); expectedDumpValue.put(Key.VALUE.toString(), mixedListexpectedDumpValue); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpNumberSet() { String varName = "oddNums"; Map dataModel = new HashMap(); Set myIntSet = new HashSet(); for (int i=0; i <= 10; i++) { if (i % 2 == 1) { myIntSet.add(i); } } dataModel.put(varName, myIntSet); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.SEQUENCE); List> myIntSetexpectedDumpValue = new ArrayList>(myIntSet.size()); for ( int i : myIntSet ) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.NUMBER); itemDump.put(Key.VALUE.toString(), i); myIntSetexpectedDumpValue.add(itemDump); } expectedDumpValue.put(Key.VALUE.toString(), myIntSetexpectedDumpValue); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpNumberCollection() { String varName = "oddNums"; Map dataModel = new HashMap(); Set odds = new HashSet(); for (int i=0; i <= 10; i++) { if (i % 2 == 1) { odds.add(i); } } TemplateCollectionModel myCollection = new SimpleCollection(odds); dataModel.put(varName, myCollection); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.COLLECTION); List> myCollectionexpectedDumpValue = new ArrayList>(odds.size()); for ( int i : odds ) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.NUMBER); itemDump.put(Key.VALUE.toString(), i); myCollectionexpectedDumpValue.add(itemDump); } expectedDumpValue.put(Key.VALUE.toString(), myCollectionexpectedDumpValue); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); test(varName, dataModel, expectedDump); } @Test public void dumpHash() { } @Test public void dumpStringToStringMap() { String varName = "capitals"; Map dataModel = new HashMap(); Map myMap = new HashMap(); myMap.put("Albany", "New York"); myMap.put("St. Paul", "Minnesota"); myMap.put("Austin", "Texas"); myMap.put("Sacramento", "California"); myMap.put("Richmond", "Virginia"); dataModel.put(varName, myMap); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.HASH_EX); SortedMap myMapExpectedDump = new TreeMap(); for ( String key : myMap.keySet() ) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.STRING); itemDump.put(Key.VALUE.toString(), myMap.get(key)); myMapExpectedDump.put(key, itemDump); } expectedDumpValue.put(Key.VALUE.toString(), (myMapExpectedDump)); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); Map dump = getDump(varName, dataModel); assertEquals(expectedDump, dump); // Test the sorting of the map List expectedKeys = new ArrayList(myMapExpectedDump.keySet()); @SuppressWarnings("unchecked") Map actualDumpValue = (Map) dump.get(varName); @SuppressWarnings("unchecked") SortedMap myMapActualDump = (SortedMap) actualDumpValue.get(Key.VALUE.toString()); List actualKeys = new ArrayList(myMapActualDump.keySet()); assertEquals(expectedKeys, actualKeys); } @Test public void dumpStringToObjectMap() { String varName = "stuff"; Map dataModel = new HashMap(); Map mixedMap = new HashMap(); String myString = "apples"; mixedMap.put("myString", myString); boolean myBool = true; mixedMap.put("myBoolean", myBool); int myInt = 4; mixedMap.put("myNumber", myInt); Date myDate = new Date(); mixedMap.put("myDate", myDate); List myList = new ArrayList(); myList.add("apples"); myList.add("bananas"); myList.add("oranges"); mixedMap.put("myList", myList); Map myMap = new HashMap(); myMap.put("Great Expectations", "Charles Dickens"); myMap.put("Pride and Prejudice", "Jane Austen"); myMap.put("Middlemarch", "George Eliot"); myMap.put("Jude the Obscure", "Thomas Hardy"); mixedMap.put("myMap", myMap); dataModel.put(varName, mixedMap); Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), Type.HASH_EX); SortedMap mixedMapExpectedDump = new TreeMap(); Map myStringExpectedDump = new HashMap(); myStringExpectedDump.put(Key.TYPE.toString(), Type.STRING); myStringExpectedDump.put(Key.VALUE.toString(), myString); mixedMapExpectedDump.put("myString", myStringExpectedDump); Map myBooleanExpectedDump = new HashMap(); myBooleanExpectedDump.put(Key.TYPE.toString(), Type.BOOLEAN); myBooleanExpectedDump.put(Key.VALUE.toString(), myBool); mixedMapExpectedDump.put("myBoolean", myBooleanExpectedDump); Map myIntExpectedDump = new HashMap(); myIntExpectedDump.put(Key.TYPE.toString(), Type.NUMBER); myIntExpectedDump.put(Key.VALUE.toString(), myInt); mixedMapExpectedDump.put("myNumber", myIntExpectedDump); Map myDateExpectedDump = new HashMap(); myDateExpectedDump.put(Key.TYPE.toString(), Type.DATE); myDateExpectedDump.put(Key.DATE_TYPE.toString(), DateType.UNKNOWN); myDateExpectedDump.put(Key.VALUE.toString(), myDate); mixedMapExpectedDump.put("myDate", myDateExpectedDump); Map myListExpectedDump = new HashMap(); myListExpectedDump.put(Key.TYPE.toString(), Type.SEQUENCE); List> myListItemsExpectedDump = new ArrayList>(myList.size()); for ( String item : myList ) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.STRING); itemDump.put(Key.VALUE.toString(), item); myListItemsExpectedDump.add(itemDump); } myListExpectedDump.put(Key.VALUE.toString(), myListItemsExpectedDump); mixedMapExpectedDump.put("myList", myListExpectedDump); Map myMapExpectedDump = new HashMap(); myMapExpectedDump.put(Key.TYPE.toString(), Type.HASH_EX); SortedMap myMapItemsExpectedDump = new TreeMap(); for ( String key : myMap.keySet() ) { Map itemDump = new HashMap(); itemDump.put(Key.TYPE.toString(), Type.STRING); itemDump.put(Key.VALUE.toString(), myMap.get(key)); myMapItemsExpectedDump.put(key, itemDump); } myMapExpectedDump.put(Key.VALUE.toString(), myMapItemsExpectedDump); mixedMapExpectedDump.put("myMap", myMapExpectedDump); expectedDumpValue.put(Key.VALUE.toString(), mixedMapExpectedDump); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); Map dump = getDump(varName, dataModel); assertEquals(expectedDump, dump); // Test the sorting of the outer map List expectedDumpValueKeys = new ArrayList(mixedMapExpectedDump.keySet()); @SuppressWarnings("unchecked") Map actualDumpValue = (Map) dump.get(varName); @SuppressWarnings("unchecked") SortedMap mixedMapActualDump = (SortedMap) actualDumpValue.get(Key.VALUE.toString()); List actualDumpValueKeys = new ArrayList(mixedMapActualDump.keySet()); assertEquals(expectedDumpValueKeys, actualDumpValueKeys); // Test the sorting of the inner map List myMapItemsExpectedDumpKeys = new ArrayList(myMapItemsExpectedDump.keySet()); @SuppressWarnings("unchecked") Map myMapActualDump = (Map) mixedMapActualDump.get("myMap"); @SuppressWarnings("unchecked") SortedMap myMapItemsActualDump = (SortedMap) myMapActualDump.get(Key.VALUE.toString()); List myMapItemsActualDumpKeys = new ArrayList(myMapItemsActualDump.keySet()); assertEquals(myMapItemsExpectedDumpKeys, myMapItemsActualDumpKeys); } @Test public void dumpObjectWithExposeNothingWrapper() { dumpObject(BeansWrapper.EXPOSE_NOTHING); } @Test public void dumpObjectWithExposePropertiesOnlyWrapper() { dumpObject(BeansWrapper.EXPOSE_PROPERTIES_ONLY); } @Test public void dumpObjectWithExposeSafeWrapper() { dumpObject(BeansWrapper.EXPOSE_SAFE); } @Test public void dumpObjectWithExposeAllWrapper() { dumpObject(BeansWrapper.EXPOSE_ALL); } /////////////////////////// Private test classes and helper methods /////////////////////////// private void test(String varName, Map dataModel, Map expectedDump) { Map dump = getDump(varName, dataModel); assertEquals(expectedDump, dump); } private void dumpObject(int exposureLevel) { String varName = "employee"; Map dataModel = new HashMap(); BeansWrapper wrapper = new BeansWrapper(); wrapper.setExposureLevel(exposureLevel); Employee employee = getEmployee(); try { dataModel.put("employee", wrapper.wrap(employee)); } catch (TemplateModelException e) { // logging is suppressed, so what do we do here? } Map expectedDumpValue = new HashMap(); expectedDumpValue.put(Key.TYPE.toString(), employee.getClass().getName()); expectedDumpValue.put(Key.VALUE.toString(), getJohnDoeExpectedDump(exposureLevel)); Map expectedDump = new HashMap(); expectedDump.put(varName, expectedDumpValue); testObjectDump(varName, dataModel, expectedDump); } private void testObjectDump(String varName, Map dataModel, Map expectedDump) { Map dump = getDump(varName, dataModel); assertEquals(expectedDump, dump); // Test the sorting of the properties @SuppressWarnings("unchecked") Map expectedVarDump = (Map) expectedDump.get(varName); @SuppressWarnings("unchecked") Map expectedValueDump = (Map) expectedVarDump.get(Key.VALUE.toString()); @SuppressWarnings("unchecked") SortedMap expectedPropertyDump = (SortedMap) expectedValueDump.get(Key.PROPERTIES.toString()); List expectedPropertyDumpKeys = new ArrayList(expectedPropertyDump.keySet()); @SuppressWarnings("unchecked") Map actualVarDump = (Map) dump.get(varName); @SuppressWarnings("unchecked") Map actualValueDump = (Map) actualVarDump.get(Key.VALUE.toString()); @SuppressWarnings("unchecked") SortedMap actualPropertyDump = (SortedMap) actualValueDump.get(Key.PROPERTIES.toString()); List actualPropertyDumpKeys = new ArrayList(actualPropertyDump.keySet()); assertEquals(expectedPropertyDumpKeys, actualPropertyDumpKeys); } private Map getDump(String varName, Map dataModel) { try { Environment env = template.createProcessingEnvironment(dataModel, new StringWriter()); return new DumpDirective().getTemplateVariableDump(varName, env); } catch (Exception e) { fail(e.getMessage()); return null; } } private class HelplessMethod implements TemplateMethodModel { @Override public Object exec(List arg0) throws TemplateModelException { return null; } } private class HelpfulMethod implements TemplateMethodModel { @Override public Object exec(List arg0) throws TemplateModelException { return null; } public Map help(String name) { return getMethodHelp(name); } } private class MethodWithStringHelp implements TemplateMethodModel { @Override public Object exec(List arg0) throws TemplateModelException { return null; } public String help(String name) { return "help"; } } private class MethodWithStringStringMapHelp implements TemplateMethodModel { @Override public Object exec(List arg0) throws TemplateModelException { return null; } public Map help(String name) { return new HashMap(); } } private class HelplessDirective implements TemplateDirectiveModel { @Override public void execute(Environment arg0, Map arg1, TemplateModel[] arg2, TemplateDirectiveBody arg3) throws TemplateException, IOException { } } private class HelpfulDirective implements TemplateDirectiveModel { @Override public void execute(Environment arg0, Map arg1, TemplateModel[] arg2, TemplateDirectiveBody arg3) throws TemplateException, IOException { } public Map help(String name) { return getDirectiveHelp(name); } } private class DirectiveWithStringHelp implements TemplateDirectiveModel { @Override public void execute(Environment arg0, Map arg1, TemplateModel[] arg2, TemplateDirectiveBody arg3) throws TemplateException, IOException { } public String help(String name) { return "help"; } } private class DirectiveWithStringStringMapHelp implements TemplateDirectiveModel { @Override public void execute(Environment arg0, Map arg1, TemplateModel[] arg2, TemplateDirectiveBody arg3) throws TemplateException, IOException { } public Map help(String name) { return new HashMap(); } } private Map getDirectiveHelp(String name) { Map map = new HashMap(); map.put("effect", "Dump the contents of a template variable."); map.put("comments", "Sequences (lists and arrays) are enclosed in square brackets. Hashes are enclosed in curly braces."); Map params = new HashMap(); params.put("var", "name of variable to dump"); map.put("parameters", params); List examples = new ArrayList(); examples.add("<@" + name + " var=\"urls\" />"); map.put("examples", examples); return map; } private Map getMethodHelp(String name) { Map map = new HashMap(); map.put("returns", "The square of the argument"); Listparams = new ArrayList(); params.add("Integer to square"); map.put("parameters", params); List examples = new ArrayList(); examples.add(name + "(4)"); map.put("examples", examples); return map; } public static class Employee { private static int count = 0; private String firstName; private String lastName; private String nickname; private Date birthdate; private boolean married; private int id; private String middleName; private List favoriteColors; private Employee supervisor; private float salary; Employee(String firstName, String lastName, int id, Date birthdate) { this.firstName = firstName; this.lastName = lastName; this.middleName = null; // test a null value this.birthdate = birthdate; this.married = true; this.id = id; this.nickname = ""; this.favoriteColors = new ArrayList(); count++; } protected void setSupervisor(Employee supervisor) { this.supervisor = supervisor; } void setSalary(float salary) { this.salary = salary; } public void setNickname(String nickname) { this.nickname = nickname; } public void setFavoriteColors(String...colors) { for (String color : colors) { favoriteColors.add(color); } } float getSalary() { return salary; } public static int getEmployeeCount() { return count; } /* Public accessor methods for templates */ public String getFullName() { return firstName + " " + lastName; } public String getName(String which) { return which == "first" ? firstName : lastName; } public String getMiddleName() { return middleName; } public String getNickname() { return nickname; } public Date getBirthdate() { return birthdate; } public int getId() { return id; } public boolean isMarried() { return married; } @Deprecated public int getFormerId() { return id % 10000; } public Employee getSupervisor() { return supervisor; } public List getFavoriteColors() { return favoriteColors; } } private Employee getEmployee() { Calendar c = Calendar.getInstance(); c.set(1982, Calendar.MAY, 5); c = DateUtils.truncate(c, Calendar.DATE); Employee jdoe = new Employee("John", "Doe", 34523, c.getTime()); jdoe.setFavoriteColors("blue", "green"); jdoe.setSalary(65000); c.clear(); c.set(1975, Calendar.OCTOBER, 25); c = DateUtils.truncate(c, Calendar.DATE); Employee jsmith = new Employee("Jane", "Smith", 78234, c.getTime()); jsmith.setFavoriteColors("red", "orange"); jdoe.setSupervisor(jsmith); return jdoe; } private Map getJohnDoeExpectedDump(int exposureLevel) { Map expectedDump = new HashMap(); // Properties SortedMap propertiesExpectedDump = new TreeMap(); if (exposureLevel < BeansWrapper.EXPOSE_NOTHING) { Map birthdateExpectedDump = new HashMap(); birthdateExpectedDump.put(Key.TYPE.toString(), Type.DATE); birthdateExpectedDump.put(Key.DATE_TYPE.toString(), DateType.UNKNOWN); Calendar c = Calendar.getInstance(); c.set(1982, Calendar.MAY, 5); c = DateUtils.truncate(c, Calendar.DATE); birthdateExpectedDump.put(Key.VALUE.toString(), c.getTime()); propertiesExpectedDump.put("birthdate", birthdateExpectedDump); Map fullNameExpectedDump = new HashMap(); fullNameExpectedDump.put(Key.TYPE.toString(), Type.STRING); fullNameExpectedDump.put(Key.VALUE.toString(), "John Doe"); propertiesExpectedDump.put("fullName", fullNameExpectedDump); Map idExpectedDump = new HashMap(); idExpectedDump.put(Key.TYPE.toString(), Type.NUMBER); idExpectedDump.put(Key.VALUE.toString(), 34523); propertiesExpectedDump.put("id", idExpectedDump); Map nicknameExpectedDump = new HashMap(); nicknameExpectedDump.put(Key.TYPE.toString(), Type.STRING); nicknameExpectedDump.put(Key.VALUE.toString(), ""); propertiesExpectedDump.put("nickname", nicknameExpectedDump); Map middleNameExpectedDump = new HashMap(); middleNameExpectedDump.put(Key.VALUE.toString(), Value.NULL); propertiesExpectedDump.put("middleName", middleNameExpectedDump); Map marriedExpectedDump = new HashMap(); marriedExpectedDump.put(Key.TYPE.toString(), Type.BOOLEAN); marriedExpectedDump.put(Key.VALUE.toString(), true); propertiesExpectedDump.put("married", marriedExpectedDump); Map supervisorExpectedDump = new HashMap(); supervisorExpectedDump.put(Key.TYPE.toString(), "freemarker.ext.dump.DumpDirectiveTest$Employee"); supervisorExpectedDump.put(Key.VALUE.toString(), getJaneSmithExpectedDump(exposureLevel)); propertiesExpectedDump.put("supervisor", supervisorExpectedDump); Map favoriteColorsExpectedDump = new HashMap(); favoriteColorsExpectedDump.put(Key.TYPE.toString(), Type.SEQUENCE); List> favoriteColorListExpectedDump = new ArrayList>(); Map color1ExpectedDump = new HashMap(); color1ExpectedDump.put(Key.TYPE.toString(), Type.STRING); color1ExpectedDump.put(Key.VALUE.toString(), "blue"); favoriteColorListExpectedDump.add(color1ExpectedDump); Map color2ExpectedDump = new HashMap(); color2ExpectedDump.put(Key.TYPE.toString(), Type.STRING); color2ExpectedDump.put(Key.VALUE.toString(), "green"); favoriteColorListExpectedDump.add(color2ExpectedDump); favoriteColorsExpectedDump.put(Key.VALUE.toString(), favoriteColorListExpectedDump); propertiesExpectedDump.put("favoriteColors", favoriteColorsExpectedDump); } expectedDump.put(Key.PROPERTIES.toString(), propertiesExpectedDump); // Methods expectedDump.put(Key.METHODS.toString(), getEmployeeMethodsExpectedDump(exposureLevel)); return expectedDump; } private List getEmployeeMethodsExpectedDump(int exposureLevel) { List expectedDump = new ArrayList(); if (exposureLevel <= BeansWrapper.EXPOSE_SAFE) { expectedDump.add("getEmployeeCount"); expectedDump.add("getName(String)"); expectedDump.add("setFavoriteColors(Strings)"); expectedDump.add("setNickname(String)"); } Collections.sort(expectedDump); return expectedDump; } private Map getJaneSmithExpectedDump(int exposureLevel) { Map expectedDump = new HashMap(); SortedMap propertiesExpectedDump = new TreeMap(); // Properties if (exposureLevel < BeansWrapper.EXPOSE_NOTHING) { Map birthdateExpectedDump = new HashMap(); birthdateExpectedDump.put(Key.TYPE.toString(), Type.DATE); birthdateExpectedDump.put(Key.DATE_TYPE.toString(), DateType.UNKNOWN); Calendar c = Calendar.getInstance(); c.set(1975, Calendar.OCTOBER, 25); c = DateUtils.truncate(c, Calendar.DATE); birthdateExpectedDump.put(Key.VALUE.toString(), c.getTime()); propertiesExpectedDump.put("birthdate", birthdateExpectedDump); Map fullNameExpectedDump = new HashMap(); fullNameExpectedDump.put(Key.TYPE.toString(), Type.STRING); fullNameExpectedDump.put(Key.VALUE.toString(), "Jane Smith"); propertiesExpectedDump.put("fullName", fullNameExpectedDump); Map idExpectedDump = new HashMap(); idExpectedDump.put(Key.TYPE.toString(), Type.NUMBER); idExpectedDump.put(Key.VALUE.toString(), 78234); propertiesExpectedDump.put("id", idExpectedDump); Map nicknameExpectedDump = new HashMap(); nicknameExpectedDump.put(Key.TYPE.toString(), Type.STRING); nicknameExpectedDump.put(Key.VALUE.toString(), ""); propertiesExpectedDump.put("nickname", nicknameExpectedDump); Map middleNameExpectedDump = new HashMap(); middleNameExpectedDump.put(Key.VALUE.toString(), Value.NULL); propertiesExpectedDump.put("middleName", middleNameExpectedDump); Map marriedExpectedDump = new HashMap(); marriedExpectedDump.put(Key.TYPE.toString(), Type.BOOLEAN); marriedExpectedDump.put(Key.VALUE.toString(), true); propertiesExpectedDump.put("married", marriedExpectedDump); Map supervisorExpectedDump = new HashMap(); supervisorExpectedDump.put(Key.VALUE.toString(), Value.NULL); propertiesExpectedDump.put("supervisor", supervisorExpectedDump); Map favoriteColorsExpectedDump = new HashMap(); favoriteColorsExpectedDump.put(Key.TYPE.toString(), Type.SEQUENCE); List> favoriteColorListExpectedDump = new ArrayList>(); Map color1ExpectedDump = new HashMap(); color1ExpectedDump.put(Key.TYPE.toString(), Type.STRING); color1ExpectedDump.put(Key.VALUE.toString(), "red"); favoriteColorListExpectedDump.add(color1ExpectedDump); Map color2ExpectedDump = new HashMap(); color2ExpectedDump.put(Key.TYPE.toString(), Type.STRING); color2ExpectedDump.put(Key.VALUE.toString(), "orange"); favoriteColorListExpectedDump.add(color2ExpectedDump); favoriteColorsExpectedDump.put(Key.VALUE.toString(), favoriteColorListExpectedDump); propertiesExpectedDump.put("favoriteColors", favoriteColorsExpectedDump); } expectedDump.put(Key.PROPERTIES.toString(), propertiesExpectedDump); // Methods expectedDump.put(Key.METHODS.toString(), getEmployeeMethodsExpectedDump(exposureLevel)); return expectedDump; } }