📄 beanswrapper.java
字号:
{
return exposureLevel;
}
/**
* Sets whether methods shadow items in beans. When true (this is the
* default value), <code>${object.name}</code> will first try to locate
* a bean method or property with the specified name on the object, and
* only if it doesn't find it will it try to call
* <code>object.get(name)</code>, the so-called "generic get method" that
* is usually used to access items of a container (i.e. elements of a map).
* When set to false, the lookup order is reversed and generic get method
* is called first, and only if it returns null is method lookup attempted.
*/
public synchronized void setMethodsShadowItems(boolean methodsShadowItems)
{
this.methodsShadowItems = methodsShadowItems;
}
boolean isMethodsShadowItems()
{
return methodsShadowItems;
}
/**
* Sets the default date type to use for date models that result from
* a plain <tt>java.util.Date</tt> instead of <tt>java.sql.Date</tt> or
* <tt>java.sql.Time</tt> or <tt>java.sql.Timestamp</tt>. Default value is
* {@link TemplateDateModel#UNKNOWN}.
* @param defaultDateType the new default date type.
*/
public synchronized void setDefaultDateType(int defaultDateType) {
this.defaultDateType = defaultDateType;
}
protected int getDefaultDateType() {
return defaultDateType;
}
/**
* Sets whether this wrapper caches model instances. Default is false.
* When set to true, calling {@link #wrap(Object)} multiple times for
* the same object will likely return the same model (although there is
* no guarantee as the cache items can be cleared anytime).
*/
public void setUseCache(boolean useCache)
{
modelCache.setUseCache(useCache);
}
/**
* Sets the null model. This model is returned from the
* {@link #wrap(Object)} method whenever the underlying object
* reference is null. It defaults to null reference, which is dealt
* with quite strictly on engine level, however you can substitute an
* arbitrary (perhaps more lenient) model, such as
* {@link freemarker.template.TemplateScalarModel#EMPTY_STRING}.
*/
public void setNullModel(TemplateModel nullModel)
{
this.nullModel = nullModel;
}
/**
* Returns the default instance of the wrapper. This instance is used
* when you construct various bean models without explicitly specifying
* a wrapper. It is also returned by
* {@link freemarker.template.ObjectWrapper#BEANS_WRAPPER}
* and this is the sole instance that is used by the JSP adapter.
* You can modify the properties of the default instance (caching,
* exposure level, null model) to affect its operation. By default, the
* default instance is not caching, uses the <code>EXPOSE_SAFE</code>
* exposure level, and uses null reference as the null model.
*/
public static final BeansWrapper getDefaultInstance()
{
return INSTANCE;
}
/**
* Wraps the object with a template model that is most specific for the object's
* class. Specifically:
* <ul>
* <li>if the object is null, returns the {@link #setNullModel(TemplateModel) null model},</li>
* <li>if the object is a Number returns a {@link NumberModel} for it,</li>
* <li>if the object is a Date returns a {@link DateModel} for it,</li>
* <li>if the object is a Boolean returns
* {@link freemarker.template.TemplateBooleanModel#TRUE} or
* {@link freemarker.template.TemplateBooleanModel#FALSE}</li>
* <li>if the object is already a TemplateModel, returns it unchanged,</li>
* <li>if the object is an array, returns a {@link ArrayModel} for it
* <li>if the object is a Map, returns a {@link MapModel} for it
* <li>if the object is a Collection, returns a {@link CollectionModel} for it
* <li>if the object is an Iterator, returns a {@link IteratorModel} for it
* <li>if the object is an Enumeration, returns a {@link EnumerationModel} for it
* <li>if the object is a String, returns a {@link StringModel} for it
* <li>otherwise, returns a generic {@link BeanModel} for it.
* </ul>
*/
public TemplateModel wrap(Object object) throws TemplateModelException
{
if(object == null)
return nullModel;
if(object instanceof TemplateModel)
return (TemplateModel)object;
if(object instanceof TemplateModelAdapter)
return ((TemplateModelAdapter)object).getTemplateModel();
if(object instanceof Map)
return modelCache.getInstance(object, simpleMapWrapper ? SimpleMapModel.FACTORY : MapModel.FACTORY);
if(object instanceof Collection)
return modelCache.getInstance(object, CollectionModel.FACTORY);
if(object.getClass().isArray())
return modelCache.getInstance(object, ArrayModel.FACTORY);
if(object instanceof Number)
return modelCache.getInstance(object, NumberModel.FACTORY);
if(object instanceof Date)
return modelCache.getInstance(object, DateModel.FACTORY);
if(object instanceof Boolean)
return ((Boolean)object).booleanValue() ? TRUE : FALSE;
if(object instanceof ResourceBundle)
return modelCache.getInstance(object, ResourceBundleModel.FACTORY);
if(object instanceof Iterator)
return new IteratorModel((Iterator)object, this);
if(object instanceof Enumeration)
return new EnumerationModel((Enumeration)object, this);
return modelCache.getInstance(object, StringModel.FACTORY);
}
protected TemplateModel getInstance(Object object, ModelFactory factory)
{
return modelCache.getInstance(object, factory);
}
protected TemplateModel create(Object object, Object factory)
{
return ((ModelFactory)factory).create(object, this);
}
/**
* Attempts to unwrap a model into underlying object. Generally, this
* method is the inverse of the {@link #wrap(Object)} method. In addition
* it will unwrap arbitrary {@link TemplateNumberModel} instances into
* a number, arbitrary {@link TemplateDateModel} instances into a date,
* {@link TemplateScalarModel} instances into a String, and
* {@link TemplateBooleanModel} instances into a Boolean.
* All other objects are returned unchanged.
*/
public Object unwrap(TemplateModel model) throws TemplateModelException
{
return unwrap(model, OBJECT_CLASS);
}
public Object unwrap(TemplateModel model, Class hint)
throws TemplateModelException
{
if(model == nullModel) {
return null;
}
// This is to be able to pass TemplateModel objects to methods that
// explicitly declare them in their argument types
if(TEMPLATE_MODEL_CLASS.isAssignableFrom(hint)) {
return model;
}
// This is for transparent interop with other wrappers (and ourselves)
// Passing the hint allows i.e. a Jython-aware method that declares a
// PyObject as its argument to receive a PyObject from a JythonModel
// passed as an argument to TemplateMethodModelEx etc.
if(model instanceof AdapterTemplateModel) {
return ((AdapterTemplateModel)model).getAdaptedObject(hint);
}
if(model instanceof WrapperTemplateModel) {
return ((WrapperTemplateModel)model).getWrappedObject();
}
// Translation of generic template models to POJOs. First give priority
// to various model interfaces based on the hint class. This helps us
// select the appropriate interface in multi-interface models when we
// know what is expected as the return type.
if(STRING_CLASS == hint) {
if(model instanceof TemplateScalarModel) {
return ((TemplateScalarModel)model).getAsString();
}
}
boolean isBoolean = Boolean.TYPE == hint;
if(isBoolean || BOOLEAN_CLASS == hint) {
if(model instanceof TemplateBooleanModel) {
return ((TemplateBooleanModel)model).getAsBoolean() ? Boolean.TRUE : Boolean.FALSE;
}
}
if(MAP_CLASS == hint) {
if(model instanceof TemplateHashModel) {
return new HashAdapter((TemplateHashModel)model, this);
}
}
if(LIST_CLASS == hint) {
if(model instanceof TemplateSequenceModel) {
return new SequenceAdapter((TemplateSequenceModel)model, this);
}
}
if(SET_CLASS == hint || COLLECTION_CLASS == hint) {
if(model instanceof TemplateCollectionModel) {
return new CollectionAdapter((TemplateCollectionModel)model, this);
}
}
// Allow one-char strings to be coerced to characters
boolean isChar = hint == Character.TYPE;
if(isChar || hint == CHARACTER_CLASS) {
if(model instanceof TemplateScalarModel) {
String s = ((TemplateScalarModel)model).getAsString();
if(s.length() == 1) {
return new Character(s.charAt(0));
}
}
}
// Primitive numeric types & Number.class
if((hint.isPrimitive() && !isChar && !isBoolean)
|| NUMBER_CLASS.isAssignableFrom(hint)) {
if(model instanceof TemplateNumberModel) {
return ((TemplateNumberModel)model).getAsNumber();
}
}
if(DATE_CLASS.isAssignableFrom(hint)) {
if(model instanceof TemplateDateModel) {
return ((TemplateDateModel)model).getAsDate();
}
}
// Translation of generic template models to POJOs. Since hint was of
// no help, now use an admittedly arbitrary order of interfaces.
if(model instanceof TemplateNumberModel)
return ((TemplateNumberModel)model).getAsNumber();
if(model instanceof TemplateDateModel)
return ((TemplateDateModel)model).getAsDate();
if(model instanceof TemplateScalarModel)
return ((TemplateScalarModel)model).getAsString();
if(model instanceof TemplateBooleanModel)
return ((TemplateBooleanModel)model).getAsBoolean() ? Boolean.TRUE : Boolean.FALSE;
if(model instanceof TemplateHashModel)
return new HashAdapter((TemplateHashModel)model, this);
if(model instanceof TemplateSequenceModel)
return new SequenceAdapter((TemplateSequenceModel)model, this);
if(model instanceof TemplateCollectionModel)
return new CollectionAdapter((TemplateCollectionModel)model, this);
// If everything else fails, return the model as-is
// (TemplateTransformModel and TemplateMethodModel[Ex] will fall into
// this category.
return model;
}
/**
* Auxiliary method that unwraps arguments for a method or constructor call.
* @param arguments the argument list of template models
* @param argTypes the preferred types of the arguments
* @return Object[] the unwrapped arguments. null if the passed list was
* null.
* @throws TemplateModelException if unwrapping any argument throws one
*/
Object[] unwrapArguments(List arguments, Class[] argTypes) throws
TemplateModelException
{
Object[] args = null;
if(arguments != null) {
int size = arguments.size();
args = new Object[size];
Iterator it = arguments.iterator();
for(int i = 0; it.hasNext(); ++i) {
args[i] = unwrap((TemplateModel)it.next(), argTypes[i]);
}
}
return args;
}
Object[] unwrapArguments(List arguments) throws TemplateModelException
{
Object[] args = null;
if(arguments != null) {
int size = arguments.size();
args = new Object[size];
Iterator it = arguments.iterator();
int i = 0;
while(it.hasNext()) {
args[i++] = unwrap((TemplateModel)it.next());
}
}
return args;
}
/**
* Invokes the specified method, wrapping the return value. The specialty
* of this method is that if the return value is null, and the return type
* of the invoked method is void, {@link TemplateModel#NOTHING} is returned.
* @param object the object to invoke the method on
* @param method the method to invoke
* @param args the arguments to the method
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -