| Method from freemarker.ext.beans.BeanModel Detail: |
public TemplateModel get(String key) throws TemplateModelException {
Class clazz = object.getClass();
Map classInfo = wrapper.getClassKeyMap(clazz);
TemplateModel retval = null;
try
{
if(wrapper.isMethodsShadowItems())
{
Object fd = classInfo.get(key);
if(fd != null)
{
retval = invokeThroughDescriptor(fd, classInfo);
} else {
retval = invokeGenericGet(classInfo, clazz, key);
}
}
else
{
TemplateModel model = invokeGenericGet(classInfo, clazz, key);
final TemplateModel nullModel = wrapper.wrap(null);
if(model != nullModel && model != UNKNOWN)
{
return model;
}
Object fd = classInfo.get(key);
if(fd != null) {
retval = invokeThroughDescriptor(fd, classInfo);
if (retval == UNKNOWN && model == nullModel) {
// This is the (somewhat subtle) case where the generic get() returns null
// and we have no bean info, so we respect the fact that
// the generic get() returns null and return null. (JR)
retval = nullModel;
}
}
}
if (retval == UNKNOWN) {
if (wrapper.isStrict()) {
throw new InvalidPropertyException("No such bean property: " + key);
} else if (logger.isDebugEnabled()) {
logNoSuchKey(key, classInfo);
}
retval = wrapper.wrap(null);
}
return retval;
}
catch(TemplateModelException e)
{
throw e;
}
catch(Exception e)
{
throw new TemplateModelException("get(" + key + ") failed on " +
"instance of " + object.getClass().getName(), e);
}
}
Uses Beans introspection to locate a property or method with name
matching the key name. If a method or property is found, it is wrapped
into freemarker.template.TemplateMethodModelEx (for a method or
indexed property), or evaluated on-the-fly and the return value wrapped
into appropriate model (for a simple property) Models for various
properties and methods are cached on a per-class basis, so the costly
introspection is performed only once per property or method of a class.
(Side-note: this also implies that any class whose method has been called
will be strongly referred to by the framework and will not become
unloadable until this class has been unloaded first. Normally this is not
an issue, but can be in a rare scenario where you create many classes on-
the-fly. Also, as the cache grows with new classes and methods introduced
to the framework, it may appear as if it were leaking memory. The
framework does, however detect class reloads (if you happen to be in an
environment that does this kind of things--servlet containers do it when
they reload a web application) and flushes the cache. If no method or
property matching the key is found, the framework will try to invoke
methods with signature
non-void-return-type get(java.lang.String),
then non-void-return-type get(java.lang.Object), or
alternatively (if the wrapped object is a resource bundle)
Object getObject(java.lang.String). |
public Object getAdaptedObject(Class hint) {
return object;
}
|
public Object getWrappedObject() {
return object;
}
|
protected boolean hasPlainGetMethod() {
return wrapper.getClassKeyMap(object.getClass()).get(BeansWrapper.GENERIC_GET_KEY) != null;
}
Whether the model has a plain get(String) or get(Object) method |
protected TemplateModel invokeGenericGet(Map keyMap,
Class clazz,
String key) throws InvocationTargetException, TemplateModelException, IllegalAccessException {
Method genericGet = (Method)keyMap.get(BeansWrapper.GENERIC_GET_KEY);
if(genericGet == null)
return UNKNOWN;
return wrapper.invokeMethod(object, genericGet, new Object[] { key });
}
|
public boolean isEmpty() {
if (object instanceof String) {
return ((String) object).length() == 0;
}
if (object instanceof Collection) {
return ((Collection) object).isEmpty();
}
if (object instanceof Map) {
return ((Map) object).isEmpty();
}
return object == null || Boolean.FALSE.equals(object);
}
Tells whether the model is empty. It is empty if either the wrapped
object is null, or it is a Boolean with false value. |
protected Set keySet() {
return wrapper.keySet(object.getClass());
}
Helper method to support TemplateHashModelEx. Returns the Set of
Strings which are available via the TemplateHashModel
interface. Subclasses that override invokeGenericGet to
provide additional hash keys should also override this method. |
public TemplateCollectionModel keys() {
return new CollectionAndSequence(new SimpleSequence(keySet(), wrapper));
}
|
public int size() {
return wrapper.keyCount(object.getClass());
}
|
public String toString() {
return object.toString();
}
|
protected Object unwrap(TemplateModel model) throws TemplateModelException {
return wrapper.unwrap(model);
}
|
public TemplateCollectionModel values() throws TemplateModelException {
List values = new ArrayList(size());
TemplateModelIterator it = keys().iterator();
while (it.hasNext()) {
String key = ((TemplateScalarModel)it.next()).getAsString();
values.add(get(key));
}
return new CollectionAndSequence(new SimpleSequence(values, wrapper));
}
|
protected TemplateModel wrap(Object obj) throws TemplateModelException {
return wrapper.getOuterIdentity().wrap(obj);
}
|