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));
}
}
}