NIHVIVO-3114 Fix problems with dump of IndividualTemplateModel.qrData()

This commit is contained in:
ryounes 2011-08-08 22:28:55 +00:00
parent d438bca997
commit 1f9bcac9b1
4 changed files with 41 additions and 14 deletions

View file

@ -1,51 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package freemarker.ext.beans;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** BeansWrapper that is more restrictive than EXPOSE_SAFE, by
* exposing getters but not setters. A setter is defined for this
* purpose as a method that returns void, or whose name
* starts with "set".
*
* @author rjy7
*
*/
public class ReadOnlyBeansWrapper extends BeansWrapper {
private static final Log log = LogFactory.getLog(ReadOnlyBeansWrapper.class);
public ReadOnlyBeansWrapper() {
// Start by exposing all safe methods.
setExposureLevel(EXPOSE_SAFE);
}
@Override
protected void finetuneMethodAppearance(Class cls, Method method, MethodAppearanceDecision decision) {
// How to define a setter? This is an approximation: a method whose name
// starts with "set" or returns void.
if ( method.getName().startsWith("set") ) {
decision.setExposeMethodAs(null);
} else if ( method.getReturnType().getName().equals("void") ) {
decision.setExposeMethodAs(null);
}
}
// For exposing a method as a property (when it's not named getX or isX). Note that this is not
// just a syntactic change in the template from X() to X, but also makes the value get precomputed.
// private void exposeAsProperty(Method method, MethodAppearanceDecision decision) {
// try {
// PropertyDescriptor pd = new PropertyDescriptor(method.getName(), method, null);
// decision.setExposeAsProperty(pd);
// decision.setMethodShadowsProperty(false);
// } catch (IntrospectionException e) {
// log.error(e, e);
// }
// }
}

View file

@ -2,6 +2,8 @@
package freemarker.ext.beans;
import java.util.Set;
/**
* Class to extract wrapper used to wrap an object into a template model object.
* Used as workaround to gap in Freemarker template model API (can't get wrapper
@ -16,4 +18,5 @@ public class WrapperExtractor {
public static int getWrapperExposureLevel(BeanModel model) {
return model.wrapper.getExposureLevel();
}
}

View file

@ -25,6 +25,7 @@ import freemarker.core.Environment;
import freemarker.ext.beans.BeanModel;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.CollectionModel;
import freemarker.ext.beans.MapModel;
import freemarker.ext.beans.SimpleMethodModel;
import freemarker.ext.beans.StringModel;
import freemarker.ext.beans.WrapperExtractor;
@ -175,6 +176,7 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
}
private Map<String, Object> getDump(TemplateModel model) throws TemplateModelException {
Map<String, Object> map = new HashMap<String, Object>();
// Don't return null if model == null. We still want to send the map to the template.
@ -308,7 +310,8 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
if ( unwrappedModel instanceof Map ) {
return getMapDump(model);
}
// Java objects are wrapped as TemplateHashModelEx-s.
// Java objects are wrapped as TemplateHashModelEx-s.
return getObjectDump(model, unwrappedModel);
}
@ -320,13 +323,18 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
TemplateModelIterator iModel = keys.iterator();
while (iModel.hasNext()) {
String key = iModel.next().toString();
// Workaround this oddity: model.object does not contain
// values for "empty" and "keys", but model.keys() does.
if ("class".equals(key) || "empty".equals(key)) {
continue;
}
TemplateModel value = model.get(key);
items.put(key, getDump(value));
}
items.put(key, getDump(value));
}
map.put(Key.VALUE.toString(), items);
return map;
}
private Map<String, Object> getObjectDump(TemplateHashModelEx model, Object object) throws TemplateModelException {
Map<String, Object> map = new HashMap<String, Object>();
@ -388,11 +396,9 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
continue;
}
}
// Else look for the entire methodName in the key set. Include those
// starting with "get" or "is" that were not found above.
// NB This does not properly account for methods exposed as properties
// using BeansWrapper.finetuneMethodAppearance(), and perhaps other
// changes to method exposure through that method.
// Else look for the entire methodName in the key set, to include
// those that are exposed as methods rather than properties.
if (keySet.contains(methodName)) {
String methodDisplayName = getMethodDisplayName(method);
// If no arguments, invoke the method to get the result