package org.beanfuse.struts2.view.freemarker; import java.util.Collection; import java.util.Map; import java.util.Set; import freemarker.core.CollectionAndSequence; import freemarker.ext.beans.MapModel; import freemarker.ext.util.ModelFactory; import freemarker.template.AdapterTemplateModel; import freemarker.template.DefaultObjectWrapper; import freemarker.template.ObjectWrapper; import freemarker.template.SimpleSequence; import freemarker.template.TemplateCollectionModel; import freemarker.template.TemplateHashModelEx; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; /** * BeanfuseWrapper不同于StrutsBeanWrapper,他扩展了DefaultObjectWrapper。提供了<br> * 1)缺省的对象包装<br> * 2)可以在set等没有顺序的模型使用?seq_contains等方法 * 3)恢复了在Map上的get方法(被DefaultObjectWrapper覆盖掉的)<br> * 4)提供了map上的values方法(等同于StrutsBeanWrapper的功能) */ public class BeanfuseWrapper extends DefaultObjectWrapper { private boolean altMapWrapper; public BeanfuseWrapper(boolean altMapWrapper) { this.altMapWrapper = altMapWrapper; } /** * 特殊包装set和map */ public TemplateModel wrap(Object obj) throws TemplateModelException { if (obj == null) { return super.wrap(null); } if (obj instanceof Collection) { return new SimpleSequence((Collection) obj, this); } if (obj instanceof Map) { if (altMapWrapper) { return new FriendlyMapModel((Map) obj, this); } else { return new MapModel((Map) obj, this); } } return super.wrap(obj); } // attempt to get the best of both the SimpleMapModel and the MapModel // of FM. protected ModelFactory getModelFactory(Class clazz) { if (altMapWrapper && Map.class.isAssignableFrom(clazz)) { return FriendlyMapModel.FACTORY; } return super.getModelFactory(clazz); } /** * Attempting to get the best of both worlds of FM's MapModel and * simplemapmodel, by reimplementing the isEmpty(), keySet() and values() * methods. ?keys and ?values built-ins are thus available, just as well as * plain Map methods. */ private final static class FriendlyMapModel extends MapModel implements TemplateHashModelEx, TemplateMethodModelEx, AdapterTemplateModel { static final ModelFactory FACTORY = new ModelFactory() { public TemplateModel create(Object object, ObjectWrapper wrapper) { return new FriendlyMapModel((Map) object, (BeanfuseWrapper) wrapper); } }; public FriendlyMapModel(Map map, BeanfuseWrapper wrapper) { super(map, wrapper); } // 将父类的&& super.isEmpty()省去了,原因不知 public boolean isEmpty() { return ((Map) object).isEmpty(); } // 此处实现与MapModel不同,MapModel中复制了一个集合 // 影响了?keySet,?size方法 protected Set keySet() { return ((Map) object).keySet(); } // add feature public TemplateCollectionModel values() { return new CollectionAndSequence(new SimpleSequence(((Map) object).values(), wrapper)); } } }