freemarker.ext.beans
Class BeansWrapper

java.lang.Object
  extended by freemarker.ext.beans.BeansWrapper
All Implemented Interfaces:
ObjectWrapper
Direct Known Subclasses:
DefaultObjectWrapper, RhinoWrapper

public class BeansWrapper
extends java.lang.Object
implements ObjectWrapper

Utility class that provides generic services to reflection classes. It handles all polymorphism issues in the wrap(Object) and unwrap(TemplateModel) methods.

Version:
$Id: BeansWrapper.java,v 1.91.2.13 2007/04/02 13:08:59 szegedia Exp $
Author:
Attila Szegedi

Field Summary
static java.lang.Object CAN_NOT_UNWRAP
           
static int EXPOSE_ALL
          At this level of exposure, all methods and properties of the wrapped objects are exposed to the template.
static int EXPOSE_NOTHING
          At this level of exposure, no bean properties and methods are exposed.
static int EXPOSE_PROPERTIES_ONLY
          At this level of exposure, only property getters are exposed.
static int EXPOSE_SAFE
          At this level of exposure, all methods and properties of the wrapped objects are exposed to the template except methods that are deemed not safe.
 
Fields inherited from interface freemarker.template.ObjectWrapper
BEANS_WRAPPER, DEFAULT_WRAPPER, SIMPLE_WRAPPER
 
Constructor Summary
BeansWrapper()
          Creates a new instance of BeansWrapper.
 
Method Summary
static java.lang.Object coerceBigDecimal(java.math.BigDecimal bd, java.lang.Class formalType)
           
static void coerceBigDecimals(java.lang.reflect.AccessibleObject callable, java.lang.Object[] args)
          Converts any BigDecimals in the passed array to the type of the corresponding formal argument of the method.
static void coerceBigDecimals(java.lang.Class[] formalTypes, java.lang.Object[] args)
          Converts any BigDecimals in the passed array to the type of the corresponding formal argument of the method.
protected  int getDefaultDateType()
          Returns the default date type.
static BeansWrapper getDefaultInstance()
          Returns the default instance of the wrapper.
 TemplateHashModel getEnumModels()
          Returns a hash model that represents the so-called class enum models.
protected  TemplateModel getInstance(java.lang.Object object, ModelFactory factory)
          Deprecated. override getModelFactory(Class) instead. Using this method will now bypass wrapper caching (if it is enabled) and always result in creation of a new wrapper. This method will be removed in 2.4
protected  ModelFactory getModelFactory(java.lang.Class clazz)
           
 ObjectWrapper getOuterIdentity()
          By default returns this.
 TemplateHashModel getStaticModels()
          Returns a hash model that represents the so-called class static models.
 boolean isExposeFields()
          Returns whether exposure of public instance fields of classes is enabled.
 boolean isSimpleMapWrapper()
          Tells whether Maps are exposed as simple maps, without access to their method.
 boolean isStrict()
           
 java.lang.Object newInstance(java.lang.Class clazz, java.util.List arguments)
           
 void setDefaultDateType(int defaultDateType)
          Sets the default date type to use for date models that result from a plain java.util.Date instead of java.sql.Date or java.sql.Time or java.sql.Timestamp.
 void setExposeFields(boolean exposeFields)
          Controls whether public instance fields of classes are exposed to templates.
 void setExposureLevel(int exposureLevel)
          Sets the method exposure level.
 void setMethodsShadowItems(boolean methodsShadowItems)
          Sets whether methods shadow items in beans.
 void setNullModel(TemplateModel nullModel)
          Sets the null model.
 void setOuterIdentity(ObjectWrapper outerIdentity)
          When wrapping an object, the BeansWrapper commonly needs to wrap "sub-objects", for example each element in a wrapped collection.
 void setSimpleMapWrapper(boolean simpleMapWrapper)
          By default the BeansWrapper wraps classes implementing java.util.Map using MapModel.
 void setStrict(boolean strict)
          Specifies if an attempt to read a bean property that doesn't exist in the wrapped object should throw an InvalidPropertyException.
 void setUseCache(boolean useCache)
          Sets whether this wrapper caches model instances.
 java.lang.Object unwrap(TemplateModel model)
          Attempts to unwrap a model into underlying object.
 java.lang.Object unwrap(TemplateModel model, java.lang.Class hint)
           
 TemplateModel wrap(java.lang.Object object)
          Wraps the object with a template model that is most specific for the object's class.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CAN_NOT_UNWRAP

public static final java.lang.Object CAN_NOT_UNWRAP

EXPOSE_ALL

public static final int EXPOSE_ALL
At this level of exposure, all methods and properties of the wrapped objects are exposed to the template.

See Also:
Constant Field Values

EXPOSE_SAFE

public static final int EXPOSE_SAFE
At this level of exposure, all methods and properties of the wrapped objects are exposed to the template except methods that are deemed not safe. The not safe methods are java.lang.Object methods wait() and notify(), java.lang.Class methods getClassLoader() and newInstance(), java.lang.reflect.Method and java.lang.reflect.Constructor invoke() and newInstance() methods, all java.lang.reflect.Field set methods, all java.lang.Thread and java.lang.ThreadGroup methods that can change its state, as well as the usual suspects in java.lang.System and java.lang.Runtime.

See Also:
Constant Field Values

EXPOSE_PROPERTIES_ONLY

public static final int EXPOSE_PROPERTIES_ONLY
At this level of exposure, only property getters are exposed. Additionally, property getters that map to unsafe methods are not exposed (i.e. Class.classLoader and Thread.contextClassLoader).

See Also:
Constant Field Values

EXPOSE_NOTHING

public static final int EXPOSE_NOTHING
At this level of exposure, no bean properties and methods are exposed. Only map items, resource bundle items, and objects retrieved through the generic get method (on objects of classes that have a generic get method) can be retrieved through the hash interface. You might want to call setMethodsShadowItems(boolean) with false value to speed up map item retrieval.

See Also:
Constant Field Values
Constructor Detail

BeansWrapper

public BeansWrapper()
Creates a new instance of BeansWrapper. The newly created instance will use the null reference as its null object, it will use EXPOSE_SAFE method exposure level, and will not cache model instances.

Method Detail

isStrict

public boolean isStrict()
See Also:
setStrict(boolean)

setStrict

public void setStrict(boolean strict)
Specifies if an attempt to read a bean property that doesn't exist in the wrapped object should throw an InvalidPropertyException.

If this property is false (the default) then an attempt to read a missing bean property is the same as reading an existing bean property whose value is null. The template can't tell the difference, and thus always can use ?default('something') and ?exists and similar built-ins to handle the situation.

If this property is true then an attempt to read a bean propertly in the template (like myBean.aProperty) that doesn't exist in the bean object (as opposed to just holding null value) will cause InvalidPropertyException, which can't be suppressed in the template (not even with myBean.noSuchProperty?default('something')). This way ?default('something') and ?exists and similar built-ins can be used to handle existing properties whose value is null, without the risk of hiding typos in the property names. Typos will always cause error. But mind you, it goes against the basic approach of FreeMarker, so use this feature only if you really know what are you doing.


setOuterIdentity

public void setOuterIdentity(ObjectWrapper outerIdentity)
When wrapping an object, the BeansWrapper commonly needs to wrap "sub-objects", for example each element in a wrapped collection. Normally it wraps these objects using itself. However, this makes it difficult to delegate to a BeansWrapper as part of a custom aggregate ObjectWrapper. This method lets you set the ObjectWrapper which will be used to wrap the sub-objects.

Parameters:
outerIdentity - the aggregate ObjectWrapper

getOuterIdentity

public ObjectWrapper getOuterIdentity()
By default returns this.

See Also:
setOuterIdentity(ObjectWrapper)

setSimpleMapWrapper

public void setSimpleMapWrapper(boolean simpleMapWrapper)
By default the BeansWrapper wraps classes implementing java.util.Map using MapModel. Setting this flag will cause it to use a SimpleMapModel instead. The biggest difference is that when using a SimpleMapModel, the map will be visible as TemplateHashModelEx, and the subvariables will be the content of the map, without the other methods and properties of the map object.

Parameters:
simpleMapWrapper - enable simple map wrapping

isSimpleMapWrapper

public boolean isSimpleMapWrapper()
Tells whether Maps are exposed as simple maps, without access to their method. See setSimpleMapWrapper(boolean) for details.

Returns:
true if Maps are exposed as simple hashes, false if they're exposed as full JavaBeans.

setExposureLevel

public void setExposureLevel(int exposureLevel)
Sets the method exposure level. By default, set to EXPOSE_SAFE.

Parameters:
exposureLevel - can be any of the EXPOSE_xxx constants.

setExposeFields

public void setExposeFields(boolean exposeFields)
Controls whether public instance fields of classes are exposed to templates.

Parameters:
exposeFields - if set to true, public instance fields of classes that do not have a property getter defined can be accessed directly by their name. If there is a property getter for a property of the same name as the field (i.e. getter "getFoo()" and field "foo"), then referring to "foo" in template invokes the getter. If set to false, no access to public instance fields of classes is given. Default is false.

isExposeFields

public boolean isExposeFields()
Returns whether exposure of public instance fields of classes is enabled. See setExposeFields(boolean) for details.

Returns:
true if public instance fields are exposed, false otherwise.

setMethodsShadowItems

public void setMethodsShadowItems(boolean methodsShadowItems)
Sets whether methods shadow items in beans. When true (this is the default value), ${object.name} 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 object.get(name), 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.


setDefaultDateType

public void setDefaultDateType(int defaultDateType)
Sets the default date type to use for date models that result from a plain java.util.Date instead of java.sql.Date or java.sql.Time or java.sql.Timestamp. Default value is TemplateDateModel.UNKNOWN.

Parameters:
defaultDateType - the new default date type.

getDefaultDateType

protected int getDefaultDateType()
Returns the default date type. See setDefaultDateType(int) for details.

Returns:
the default date type

setUseCache

public void setUseCache(boolean useCache)
Sets whether this wrapper caches model instances. Default is false. When set to true, calling 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).


setNullModel

public void setNullModel(TemplateModel nullModel)
Sets the null model. This model is returned from the 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 TemplateScalarModel.EMPTY_STRING.


getDefaultInstance

public static final BeansWrapper getDefaultInstance()
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 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 EXPOSE_SAFE exposure level, and uses null reference as the null model.


wrap

public TemplateModel wrap(java.lang.Object object)
                   throws TemplateModelException
Wraps the object with a template model that is most specific for the object's class. Specifically:

Specified by:
wrap in interface ObjectWrapper
Returns:
a TemplateModel wrapper of the object passed in.
Throws:
TemplateModelException

getInstance

protected TemplateModel getInstance(java.lang.Object object,
                                    ModelFactory factory)
Deprecated. override getModelFactory(Class) instead. Using this method will now bypass wrapper caching (if it is enabled) and always result in creation of a new wrapper. This method will be removed in 2.4

Parameters:
object -
factory -

getModelFactory

protected ModelFactory getModelFactory(java.lang.Class clazz)

unwrap

public java.lang.Object unwrap(TemplateModel model)
                        throws TemplateModelException
Attempts to unwrap a model into underlying object. Generally, this method is the inverse of the wrap(Object) method. In addition it will unwrap arbitrary TemplateNumberModel instances into a number, arbitrary TemplateDateModel instances into a date, TemplateScalarModel instances into a String, and TemplateBooleanModel instances into a Boolean. All other objects are returned unchanged.

Throws:
TemplateModelException

unwrap

public java.lang.Object unwrap(TemplateModel model,
                               java.lang.Class hint)
                        throws TemplateModelException
Throws:
TemplateModelException

getStaticModels

public TemplateHashModel getStaticModels()
Returns a hash model that represents the so-called class static models. Every class static model is itself a hash through which you can call static methods on the specified class. To obtain a static model for a class, get the element of this hash with the fully qualified class name. For example, if you place this hash model inside the root data model under name "statics", you can use i.e. statics["java.lang. System"]. currentTimeMillis() to call the System.currentTimeMillis() method.

Returns:
a hash model whose keys are fully qualified class names, and that returns hash models whose elements are the static models of the classes.

getEnumModels

public TemplateHashModel getEnumModels()
Returns a hash model that represents the so-called class enum models. Every class' enum model is itself a hash through which you can access enum value declared by the specified class, assuming that class is an enumeration. To obtain an enum model for a class, get the element of this hash with the fully qualified class name. For example, if you place this hash model inside the root data model under name "enums", you can use i.e. statics["java.math.RoundingMode"].UP to access the RoundingMode.UP value.

Returns:
a hash model whose keys are fully qualified class names, and that returns hash models whose elements are the enum models of the classes.
Throws:
java.lang.UnsupportedOperationException - if this method is invoked on a pre-1.5 JRE, as Java enums aren't supported there.

newInstance

public java.lang.Object newInstance(java.lang.Class clazz,
                                    java.util.List arguments)
                             throws TemplateModelException
Throws:
TemplateModelException

coerceBigDecimals

public static void coerceBigDecimals(java.lang.reflect.AccessibleObject callable,
                                     java.lang.Object[] args)
Converts any BigDecimals in the passed array to the type of the corresponding formal argument of the method.


coerceBigDecimals

public static void coerceBigDecimals(java.lang.Class[] formalTypes,
                                     java.lang.Object[] args)
Converts any BigDecimals in the passed array to the type of the corresponding formal argument of the method.


coerceBigDecimal

public static java.lang.Object coerceBigDecimal(java.math.BigDecimal bd,
                                                java.lang.Class formalType)