NIHVIVO-3087 Add parens to method display name in dump of argumentless method

This commit is contained in:
ryounes 2011-08-05 14:35:50 +00:00
parent 74c0edabda
commit 4229e04a02
4 changed files with 43 additions and 38 deletions

View file

@ -182,11 +182,4 @@ public abstract class BaseIndividualTemplateModel extends BaseTemplateModel {
return id; return id;
} }
public String ageInUnits(String units) {
return "5 " + units;
}
public int age() {
return 10;
}
} }

View file

@ -4,12 +4,12 @@ package freemarker.ext.beans;
import java.lang.reflect.Member; import java.lang.reflect.Member;
/** /**
* Class to extract information about the wrapper used to wrap an object in * Class to expose protected information about template models and their data
* the template model. * and wrappers to dump methods. Used as workaround to some problems and gaps
* in the Freemarker template model API.
*/ */
public class WrapperExtractor { public class WrapperUtils {
public static BeansWrapper getWrapper(BeanModel model) { public static BeansWrapper getWrapper(BeanModel model) {
return model.wrapper; return model.wrapper;

View file

@ -23,11 +23,12 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import freemarker.core.Environment; import freemarker.core.Environment;
import freemarker.ext.beans.BeanModel;
import freemarker.ext.beans.BeansWrapper; import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.CollectionModel; import freemarker.ext.beans.CollectionModel;
import freemarker.ext.beans.SimpleMethodModel; import freemarker.ext.beans.SimpleMethodModel;
import freemarker.ext.beans.StringModel; import freemarker.ext.beans.StringModel;
import freemarker.ext.beans.WrapperExtractor; import freemarker.ext.beans.WrapperUtils;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateBooleanModel; import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateCollectionModel; import freemarker.template.TemplateCollectionModel;
@ -176,9 +177,9 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
if ( model instanceof TemplateSequenceModel ) { if ( model instanceof TemplateSequenceModel ) {
if (model instanceof CollectionModel && ! ((CollectionModel)model).getSupportsIndexedAccess()) { if (model instanceof CollectionModel && ! ((CollectionModel)model).getSupportsIndexedAccess()) {
map.putAll( getTemplateModelDump( ( TemplateCollectionModel)model ) ); map.putAll( getTemplateModelDump( (TemplateCollectionModel)model ) );
} else { } else {
map.putAll( getTemplateModelDump( ( TemplateSequenceModel)model ) ); map.putAll( getTemplateModelDump( (TemplateSequenceModel)model ) );
} }
} else if ( model instanceof TemplateNumberModel ) { } else if ( model instanceof TemplateNumberModel ) {
@ -191,7 +192,7 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
map.putAll( getTemplateModelDump( (TemplateDateModel)model ) ); map.putAll( getTemplateModelDump( (TemplateDateModel)model ) );
} else if ( model instanceof TemplateCollectionModel ) { } else if ( model instanceof TemplateCollectionModel ) {
map.putAll( getTemplateModelDump( ( TemplateCollectionModel)model ) ); map.putAll( getTemplateModelDump( (TemplateCollectionModel)model ) );
} else if ( model instanceof StringModel ) { } else if ( model instanceof StringModel ) {
// A StringModel can wrap either a String or a plain Java object. // A StringModel can wrap either a String or a plain Java object.
@ -201,17 +202,17 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
if (unwrappedModel instanceof String) { if (unwrappedModel instanceof String) {
map.putAll( getTemplateModelDump( (TemplateScalarModel)model ) ); map.putAll( getTemplateModelDump( (TemplateScalarModel)model ) );
} else { } else {
map.putAll( getTemplateModelDump( ( TemplateHashModelEx)model ) ); map.putAll( getTemplateModelDump( (TemplateHashModelEx)model ) );
} }
} else if ( model instanceof TemplateScalarModel ) { } else if ( model instanceof TemplateScalarModel ) {
map.putAll( getTemplateModelDump( (TemplateScalarModel)model ) ); map.putAll( getTemplateModelDump( (TemplateScalarModel)model ) );
} else if ( model instanceof TemplateHashModelEx ) { } else if ( model instanceof TemplateHashModelEx ) {
map.putAll( getTemplateModelDump( ( TemplateHashModelEx)model ) ); map.putAll( getTemplateModelDump( (TemplateHashModelEx)model ) );
} else if (model instanceof TemplateHashModel ) { } else if (model instanceof TemplateHashModel ) {
map.putAll( getTemplateModelDump( ( TemplateHashModel)model ) ); map.putAll( getTemplateModelDump( (TemplateHashModel)model ) );
// Nodes and transforms not included here // Nodes and transforms not included here
@ -389,27 +390,29 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
// changes to method exposure through that method. // changes to method exposure through that method.
if (keySet.contains(methodName)) { if (keySet.contains(methodName)) {
String methodDisplayName = getMethodDisplayName(method); String methodDisplayName = getMethodDisplayName(method);
if ( methodDisplayName.endsWith(")") ) { // If no arguments, invoke the method to get the result
if ( methodDisplayName.endsWith("()") ) {
SimpleMethodModel methodModel = (SimpleMethodModel)model.get(methodName);
Member member = WrapperUtils.getMember(methodModel);
try {
if (member instanceof Method) {
Method m = (Method) member;
Object result = m.invoke(object);
BeansWrapper wrapper = getWrapper(model);
TemplateModel wrappedResult = wrapper.wrap(result);
methods.put(methodDisplayName, getDump(wrappedResult));
}
} catch (Exception e) {
log.error(e, e);
}
// Else display method name, parameter types, and return type
} else {
String returnTypeName = getTypeName(method.getReturnType()); String returnTypeName = getTypeName(method.getReturnType());
Map<String, String> methodValue = new HashMap<String, String>(); Map<String, String> methodValue = new HashMap<String, String>();
if ( ! returnTypeName.equals("void") ) { if ( ! returnTypeName.equals("void") ) {
methodValue.put(Key.TYPE.toString(), returnTypeName); methodValue.put(Key.TYPE.toString(), returnTypeName);
} }
methods.put(methodDisplayName, methodValue); methods.put(methodDisplayName, methodValue);
} else {
SimpleMethodModel methodModel = (SimpleMethodModel)model.get(methodName);
Member member = WrapperExtractor.getMember(methodModel);
try {
if (member instanceof Method) {
Method m = (Method) member;
Object result = m.invoke(object);
// But we need to use the same wrapper that wrapped it
TemplateModel wrappedResult = new BeansWrapper().wrap(result);
methods.put(methodDisplayName, getDump(wrappedResult));
}
} catch (Exception e) {
log.error(e, e);
}
} }
} }
} }
@ -423,16 +426,25 @@ public abstract class BaseDumpDirective implements TemplateDirectiveModel {
return map; return map;
} }
private BeansWrapper getWrapper(TemplateHashModelEx model) {
if (model instanceof BeanModel) {
return WrapperUtils.getWrapper((BeanModel)model);
} else {
return new BeansWrapper();
}
}
private String getMethodDisplayName(Method method) { private String getMethodDisplayName(Method method) {
String methodName = method.getName(); String methodName = method.getName();
Class<?>[] paramTypes = method.getParameterTypes(); Class<?>[] paramTypes = method.getParameterTypes();
List<String> paramTypeList = new ArrayList<String>(paramTypes.length);
if (paramTypes.length > 0) { if (paramTypes.length > 0) {
List<String> paramTypeList = new ArrayList<String>(paramTypes.length);
for (Class<?> cls : paramTypes) { for (Class<?> cls : paramTypes) {
paramTypeList.add(getTypeName(cls)); paramTypeList.add(getTypeName(cls));
} }
methodName += "(" + StringUtils.join(paramTypeList, ", ") + ")";
} }
methodName += "(" + StringUtils.join(paramTypeList, ", ") + ")";
return methodName; return methodName;
} }

View file

@ -1236,12 +1236,12 @@ public class DumpDirectiveTest {
Map<String, Object> familyNameExpectedDump = new HashMap<String, Object>(); Map<String, Object> familyNameExpectedDump = new HashMap<String, Object>();
familyNameExpectedDump.put(Key.TYPE.toString(), Type.STRING); familyNameExpectedDump.put(Key.TYPE.toString(), Type.STRING);
familyNameExpectedDump.put(Key.VALUE.toString(), familyName); familyNameExpectedDump.put(Key.VALUE.toString(), familyName);
expectedDump.put("familyName", familyNameExpectedDump); expectedDump.put("familyName()", familyNameExpectedDump);
Map<String, Object> employeeCountExpectedDump = new HashMap<String, Object>(); Map<String, Object> employeeCountExpectedDump = new HashMap<String, Object>();
employeeCountExpectedDump.put(Key.TYPE.toString(), Type.NUMBER); employeeCountExpectedDump.put(Key.TYPE.toString(), Type.NUMBER);
employeeCountExpectedDump.put(Key.VALUE.toString(), Employee.getEmployeeCount()); employeeCountExpectedDump.put(Key.VALUE.toString(), Employee.getEmployeeCount());
expectedDump.put("getEmployeeCount", employeeCountExpectedDump); expectedDump.put("getEmployeeCount()", employeeCountExpectedDump);
} }
return expectedDump; return expectedDump;