Interface MethodCallAwareTemplateHashModel
- All Superinterfaces:
TemplateHashModel
,TemplateModel
- All Known Implementing Classes:
GenericObjectModel
TemplateHashModel
that can return different result than TemplateHashModel.get(String)
,
knowing that the result of it will be called as a method. At least as of 2.3.33, this is only used by the
template language for 0-argument method calls that are directly after the dot operator and the key (like in
obj.m()
, where the "()" is directly after the key "m"), or for the equivalent of that with square brackets
(obj["m"]()
).
Background knowledge needed to understand this: In the FreeMarker template language, methods/functions are
first class values (just like strings, numbers,etc.). Also, unlike in Java, there's no separate namespace for
methods, and for the other field-like members. When you have obj.m()
in a template, first, the dot operator
gets the value for the key "m", and after that, and independently of that, the method call operator tries to call
that value (and if it's not a method or function, that will fail). The dot operator, before 2.3.33, was never aware
of what the value it gets will be used for (like will it be called, will it be printed, etc.). Now it can be.
For example, if in the template you have someRecord.someComponent()
, and there someRecord
was wrapped
by the ObjectWrapper
into a TemplateHashModel
that also implements this interface, then the dot
operator will call getBeforeMethodCall("someComponent")
, rather than
get("someComponent")
. This is needed to implement subtle features like
BeansWrapper.MethodAppearanceDecision.setMethodInsteadOfPropertyValueBeforeCall(boolean)
,
which is needed to implement
ZeroArgumentNonVoidMethodPolicy.BOTH_METHOD_AND_PROPERTY_UNLESS_BEAN_PROPERTY_READ_METHOD
.
While technically we could do the same for method calls with more the 0 arguments, as of 2.3.33 at least, we
don't want to generalize this to that case. This is a workaround we added to address the issue with accessing
components in Java records, which are 0-argument methods (see that at
BeansWrapper.MethodAppearanceDecision.setMethodInsteadOfPropertyValueBeforeCall(boolean)
).
Objects wrapped with BeansWrapper
, and hence with DefaultObjectWrapper
, will implement this
interface when they are "generic" objects (that is, when they are not classes with special wrapper, like
Map
-s, Collection
-s, Number
-s, etc.).
- Since:
- 2.3.33
-
Nested Class Summary
Modifier and TypeInterfaceDescriptionstatic class
Thrown bygetBeforeMethodCall(String)
; see there. -
Field Summary
Fields inherited from interface freemarker.template.TemplateModel
NOTHING
-
Method Summary
Modifier and TypeMethodDescriptiongetBeforeMethodCall(String key)
This is called instead ofTemplateHashModel.get(String)
if we know that the return value should be callable like a method.Methods inherited from interface freemarker.template.TemplateHashModel
get, isEmpty
-
Method Details
-
getBeforeMethodCall
TemplateModel getBeforeMethodCall(String key) throws TemplateModelException, MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodExceptionThis is called instead ofTemplateHashModel.get(String)
if we know that the return value should be callable like a method. The advantage of this is that we can coerce the value to a method when desirable, and otherwise can give a more specific error message in the resulting exception than the standardNonMethodException
would.- Parameters:
key
- Same as forTemplateHashModel.get(String)
- Returns:
- Same as for
TemplateHashModel.get(String)
, except it should return aTemplateMethodModel
(aTemplateMethodModelEx
if possible), or in very rare case aMacro
that was created with thefunction
directive. Or,null
in the same case asTemplateHashModel.get(String)
. The method should never return something that's not callable in the template language as a method or function; the return type isTemplateModel
because that's the most specific common super-interface ofTemplateMethodModel
, andMacro
. - Throws:
MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException
- If the value for the given key exists, but shouldn't be coerced to something callable as a method. This will be converted toNonMethodException
by the engine, but in this exception you can optionally give a more specific explanation, and that will be added to the resultingNonMethodException
as a hint to the user.TemplateModelException
-