MethodCallAwareTemplateHashModel (FreeMarker 2.3.35 API)
Description: declaration: package: freemarker.template, interface: MethodCallAwareTemplateHashModel

Package freemarker.template

# Interface MethodCallAwareTemplateHashModel

All Superinterfaces:
  `TemplateHashModel`, `TemplateModel`

All Known Implementing Classes:
  `GenericObjectModel`

public interface MethodCallAwareTemplateHashModel extends TemplateHashModel
Adds an extra getter method to `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

  Nested Classes
  Modifier and Type
  Interface
  Description
  `static class`
  `MethodCallAwareTemplateHashModel.ShouldNotBeGetAsMethodException`
  Thrown by `getBeforeMethodCall(String)`; see there.

- ## Field Summary

  ### Fields inherited from interface freemarker.template.TemplateModel

  `NOTHING`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `TemplateModel`
  `getBeforeMethodCall​(String key)`
  This is called instead of `TemplateHashModel.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.ShouldNotBeGetAsMethodException
    This is called instead of `TemplateHashModel.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 standard `NonMethodException` would.
    Parameters:
      `key` - Same as for `TemplateHashModel.get(String)`
    Returns:
      Same as for `TemplateHashModel.get(String)`, except it should return a `TemplateMethodModel` (a `TemplateMethodModelEx` if possible), or in very rare case a `Macro` that was created with the `function` directive. Or, `null` in the same case as `TemplateHashModel.get(String)`. The method should never return something that's not callable in the template language as a method or function; the return type is `TemplateModel` because that's the most specific common super-interface of `TemplateMethodModel`, and `Macro`.
    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 to `NonMethodException` by the engine, but in this exception you can optionally give a more specific explanation, and that will be added to the resulting `NonMethodException` as a hint to the user.
      `TemplateModelException`