NIHVIVO-2479 Finalize dump template

This commit is contained in:
ryounes 2011-04-22 19:45:45 +00:00
parent 27b78c2760
commit 8f0b6f7b01
5 changed files with 327 additions and 43 deletions

View file

@ -0,0 +1,253 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
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 org.apache.commons.lang.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.SimpleCollection;
import freemarker.template.TemplateModelException;
/**
* Test of dump directives
* @author rjy7
*
*/
public class DumpTestController extends FreemarkerHttpServlet {
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(TestController.class);
private static final String TEMPLATE_DEFAULT = "test.ftl";
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
//Portal portal = vreq.getPortal();
Map<String, Object> body = new HashMap<String, Object>();
body.put("title", "Freemarker Test");
body.put("dog", "Rover");
body.put("int", 7);
body.put("bool", false);
body.put("now", new Date());
java.sql.Date date = new java.sql.Date(1302297332043L);
body.put("date", date);
Time time = new Time(1302297332043L);
body.put("time", time);
Timestamp ts = new Timestamp(1302297332043L);
body.put("timestamp", ts);
// List of strings
List<String> fruit = new ArrayList<String>();
fruit.add("apples");
fruit.add("bananas");
fruit.add("peaches");
body.put("fruit", fruit);
// Mixed list
List<Object> mixedList = new ArrayList<Object>();
String myString = "apples";
mixedList.add(myString);
int myInt = 4;
mixedList.add(myInt);
boolean myBool = true;
mixedList.add(myBool);
List<String> myList = new ArrayList<String>();
myList.add("dog");
myList.add("cat");
myList.add("elephant");
mixedList.add(myList);
body.put("mixedList", mixedList);
// Collection (non-indexable)
Set<Integer> odds = new HashSet<Integer>();
for (int i=0; i <= 10; i++) {
if (i % 2 == 1) {
odds.add(i);
}
}
body.put("oddNums", new SimpleCollection(odds));
// String-string map
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("Albany", "New York");
myMap.put("St. Paul", "Minnesota");
myMap.put("Austin", "Texas");
myMap.put("Sacramento", "California");
myMap.put("Richmond", "Virginia");
body.put("capitals", myMap);
// Mixed map
Map<String, Object> mixedMap = new HashMap<String, Object>();
mixedMap.put("myString", myString);
mixedMap.put("myBoolean", myBool);
mixedMap.put("myNumber", myInt);
Date myDate = new Date();
mixedMap.put("myDate", myDate);
mixedMap.put("myList", myList);
mixedMap.put("capitals", myMap);
body.put("mixedMap", mixedMap);
// Java object
Employee jdoe = getEmployee();
body.put("employeeLimited", jdoe);
try {
body.put("employeeInvisible", wrap(jdoe, BeansWrapper.EXPOSE_NOTHING));
body.put("employeeFull", wrap(jdoe, BeansWrapper.EXPOSE_SAFE));
} catch (TemplateModelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new TemplateResponseValues(TEMPLATE_DEFAULT, body);
}
@Override
protected String getTitle(String siteName, VitroRequest vreq) {
return "Test";
}
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<String> 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<String>();
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<String> 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;
}
}

View file

@ -255,7 +255,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
return UrlBuilder.getUrl(path);
}
protected TemplateModel wrap(int exposureLevel, Object obj) throws TemplateModelException {
protected TemplateModel wrap(Object obj, int exposureLevel) throws TemplateModelException {
BeansWrapper wrapper = getBeansWrapper(exposureLevel);
return wrapper.wrap(obj);
}
@ -271,7 +271,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
// instead of the configuration's object wrapper, which doesn't. The templates can
// add stylesheets and scripts to the lists by calling their add() methods.
try {
return wrap(BeansWrapper.EXPOSE_SAFE, new Tags());
return wrap(new Tags(), BeansWrapper.EXPOSE_SAFE);
} catch (TemplateModelException e) {
log.error("Error creating Tags template model");
return null;

View file

@ -133,7 +133,7 @@ public class IndividualController extends FreemarkerHttpServlet {
* This is still safe, because we are only putting BaseTemplateModel objects
* into the data model: no real data can be modified.
*/
body.put("individual", wrap(BeansWrapper.EXPOSE_SAFE, itm));
body.put("individual", wrap(itm, BeansWrapper.EXPOSE_SAFE));
body.put("headContent", getRdfLinkTag(itm));
String template = getIndividualTemplate(individual, vreq);

View file

@ -1011,7 +1011,7 @@ public class DumpDirectiveTest {
// Properties
SortedMap<String, Object> propertiesExpectedDump = new TreeMap<String, Object>();
if (exposureLevel != BeansWrapper.EXPOSE_NOTHING) {
if (exposureLevel < BeansWrapper.EXPOSE_NOTHING) {
Map<String, Object> birthdateExpectedDump = new HashMap<String, Object>();
birthdateExpectedDump.put(Key.TYPE.toString(), Type.DATE);
@ -1078,7 +1078,7 @@ public class DumpDirectiveTest {
private List<String> getEmployeeMethodsExpectedDump(int exposureLevel) {
List<String> expectedDump = new ArrayList<String>();
if (exposureLevel == BeansWrapper.EXPOSE_SAFE || exposureLevel == BeansWrapper.EXPOSE_ALL) {
if (exposureLevel <= BeansWrapper.EXPOSE_SAFE) {
expectedDump.add("getEmployeeCount");
expectedDump.add("getName(String)");
expectedDump.add("setFavoriteColors(Strings)");
@ -1095,7 +1095,7 @@ public class DumpDirectiveTest {
SortedMap<String, Object> propertiesExpectedDump = new TreeMap<String, Object>();
// Properties
if (exposureLevel != BeansWrapper.EXPOSE_NOTHING) {
if (exposureLevel < BeansWrapper.EXPOSE_NOTHING) {
Map<String, Object> birthdateExpectedDump = new HashMap<String, Object>();
birthdateExpectedDump.put(Key.TYPE.toString(), Type.DATE);

View file

@ -31,6 +31,10 @@ div.dump {
.dump ul li.item .value {
margin-left: 1.5em;
}
.dump ul.methods li {
margin-bottom: .25em;
}
</style>
<div class="dump">
@ -45,39 +49,61 @@ div.dump {
<#list dump?keys as key>
<li>
<p><strong>Variable name:</strong> ${key}</p>
<@doMap dump[key] />
<#local type = dump[key].type>
<#if type == "Directive" || type == "Method">
<@doMethod dump[key] />
<#else>
<@doTypeAndValue dump[key] />
</#if>
</li>
</#list>
</ul>
</#if>
</#macro>
<#macro doMap map>
<#if map.type?has_content>
<p><strong>Type:</strong> ${map.type}</p>
<#macro doTypeAndValue map>
<#local type = map.type!>
<#if type?has_content>
<p><strong>Type:</strong> ${type}</p>
<#if map.dateType?has_content>
<p><strong>Date type:</strong> ${map.dateType}</p>
</#if>
</#if>
<#if map.type == "Directive" || map.type == "Method">
<@doHelp map.help! />
<#else>
<@doValue map.type map.value! />
</#if>
</#macro>
<#macro doValue type value="">
<div class="values">
<#local value = map.value!>
<#if value??>
<#if value?is_sequence><@doSequenceValue value type/>
<div class="values">
<#if type?contains(".")><@doObjectValue value />
<#elseif value?is_sequence><@doSequenceValue value type />
<#elseif value?is_hash_ex><@doMapValue value />
<#else><@doScalarValue type value />
</#if>
<#else><@doScalarValue value />
</#if>
</div>
</#if>
</#macro>
<#macro doObjectValue obj>
<#if obj.properties?has_content>
<p><strong>Properties:</strong></p>
<ul class="properties">
<#list obj.properties?keys as property>
<@liItem>
${property} => <@divValue><@doTypeAndValue obj.properties[property] /></@divValue>
</@liItem>
</#list>
</ul>
</#if>
<#if obj.methods?has_content>
<p><strong>Methods:</strong</p>
<ul class="methods">
<#list obj.methods as method>
<@liItem>${method}</@liItem>
</#list>
</ul>
</#if>
</#macro>
<#macro doSequenceValue seq type>
@ -85,14 +111,13 @@ div.dump {
<#if seq?has_content>
<ul class="sequence">
<#list seq as item>
<li class="item">
<@liItem>
<#if type == "Sequence">
Item ${item_index}:
<@valueDiv><@doMap item /></@valueDiv>
<#else><@doMap item />
<@divValue><@doTypeAndValue item /></@divValue>
<#else><@doTypeAndValue item />
</#if>
</li>
</@liItem>
</#list>
</ul>
<#else>no values
@ -104,33 +129,35 @@ div.dump {
<#if map?has_content>
<ul class="map">
<#list map?keys as key>
<li class="item">
${key} => <@valueDiv><@doMap map[key] /></@valueDiv>
</li>
<@liItem>
${key} => <@divValue><@doTypeAndValue map[key] /></@divValue>
</@liItem>
</#list>
</ul>
<#else>no values
</#if>
</#macro>
<#macro doScalarValue type value>
<#macro doScalarValue value>
<strong>Value:</strong>
<#if value?is_string || value?is_number>${value}
<#if value?is_string>${value}
<#elseif value?is_number>${value?c}
<#elseif value?is_boolean>${value?string}
<#elseif value?is_date>${value?string("EEEE, MMMM dd, yyyy hh:mm:ss a zzz")}
<#else>no value
</#if>
</#macro>
<#macro doHelp help="">
<#macro doMethod method>
<p><strong>Type:</strong> ${method.type}</p>
<#local help = method.help>
<#if help?has_content>
<p><strong>Help:</strong><p>
<ul class="help">
<#list help?keys as key>
<li>
<#local value = help[key]>
<@valueDiv>
<@divValue>
<#if value?is_string><p><strong>${key?capitalize}:</strong> ${value}</p>
<#else>
<p><strong>${key?capitalize}:</strong></p>
@ -146,17 +173,21 @@ div.dump {
</#if>
</ul>
</#if>
</@valueDiv>
</@divValue>
</li>
</#list>
</ul>
</#if>
</#macro>
<#macro valueDiv>
<#macro divValue>
<div class="value"><#nested></div>
</#macro>
<#macro liItem>
<li class="item"><#nested></li>
</#macro>
<#-- This will work after we move stylesheets to Configuration sharedVariables
${stylesheets.add('<link rel="stylesheet" href="/css/fmdump.css">')}