MethodAppearanceFineTuner (FreeMarker 2.3.35 API)
Description: declaration: package: freemarker.ext.beans, interface: MethodAppearanceFineTuner

Package freemarker.ext.beans

# Interface MethodAppearanceFineTuner

public interface MethodAppearanceFineTuner
Used for customizing how the Java methods are visible from templates, via `BeansWrapper.setMethodAppearanceFineTuner(MethodAppearanceFineTuner)`. The object that implements this should also implement `SingletonCustomizer` whenever possible, to allow reusing the class introspection cache in more situations.

Since:
  2.3.21

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `process​(BeansWrapper.MethodAppearanceDecisionInput in, BeansWrapper.MethodAppearanceDecision out)`
  Implement this to tweak certain aspects of how methods appear in the data-model.

- ## Method Details

  - ### process

    void process​(BeansWrapper.MethodAppearanceDecisionInput in, BeansWrapper.MethodAppearanceDecision out)
    Implement this to tweak certain aspects of how methods appear in the data-model. `BeansWrapper` will pass in all Java methods here that it intends to expose in the data-model as methods (so you can do `obj.foo()` in the template). This also applies to JavaBeans property read methods, like `public int getX()`, even if the bean property value itself is already exposed (with name `x`, in this example).

    With this method you can do the following tweaks:

    - Hide a method that would be otherwise shown by calling `BeansWrapper.MethodAppearanceDecision.setExposeMethodAs(String)` with `null` parameter. Note that you can't un-hide methods that are not public or are considered to by unsafe (like `Object.wait()`) because `process(freemarker.ext.beans.BeansWrapper.MethodAppearanceDecisionInput, freemarker.ext.beans.BeansWrapper.MethodAppearanceDecision)` is not called for those.
    - Show the method with a different name in the data-model than its real name by calling `BeansWrapper.MethodAppearanceDecision.setExposeMethodAs(String)` with non-`null` parameter. (If set to `null`, then the method won't be exposed.) The default is the real name of the method. Note that if `methodInsteadOfPropertyValueBeforeCall` is `true`, the method is not exposed if the method name set here is the same as the name of the property set for this method with `BeansWrapper.MethodAppearanceDecision.setExposeAsProperty(PropertyDescriptor)`.
    - Create a fake JavaBean property for this method by calling `BeansWrapper.MethodAppearanceDecision.setExposeAsProperty(PropertyDescriptor)`. For example, if you have `int size()` in a class, but you want it to be accessed from the templates as `obj.size` (like a JavaBean property), rather than as `obj.size()`, you can do that with this (but remember calling `setMethodShadowsProperty(false)` as well, if the method name is exactly the same as the property name). The default is `null`, which means that no fake property is created for the method. You need not, and shouldn't set this to non-`null` for the property read (get/is) methods of real JavaBeans properties, as bean properties are not treated as methods (hence the `MethodAppearanceFineTuner` is irrelevant), and are exposed or not regardless of this mechanism (based on `BeansWrapperConfiguration.setExposureLevel(int)`). The property name in the `PropertyDescriptor` can be anything, but the method (or methods) in it must belong to the class that is given as the `clazz` parameter, or it must be inherited from that class, otherwise the behavior is undefined, and errors can occur later. `IndexedPropertyDescriptor`-s are supported. If a real JavaBeans property of the same name exists, or a fake property of the same name was already assigned earlier, it won't be replaced by the new one by default, however this can be changed with `BeansWrapper.MethodAppearanceDecision.setReplaceExistingProperty(boolean)`.
    - If something is exposed as property via `BeansWrapper.MethodAppearanceDecision.setExposeAsProperty(PropertyDescriptor)` (and not only because it's a real JavaBeans property), and you also want the property value to be accessible in templates as the return value of a 0-argument method of the same name, then call `BeansWrapper.MethodAppearanceDecision.setMethodInsteadOfPropertyValueBeforeCall(boolean)` with `true`. Here's an example to explain that. Let's say, you have a class that contains "public String name()", and you exposed that as a property via `BeansWrapper.MethodAppearanceDecision.setExposeAsProperty(PropertyDescriptor)`. So far, you can access the property value from templates as `user.name`, but `user.name()` will fail, saying that you try to call a `String` (because you apply the `()` operator on the result of `user.name`, which is a `String`). But with `BeansWrapper.MethodAppearanceDecision.setMethodInsteadOfPropertyValueBeforeCall(boolean)` `true`, both `user.name`, and `user.name()` will do the same (which is possible because if `user` is a `MethodCallAwareTemplateHashModel`, "name" can be resoled to different values in the two cases). The default (initial) value of `methodInsteadOfPropertyValueBeforeCall` depends on `BeansWrapperConfiguration.setDefaultZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)`, and `BeansWrapperConfiguration.setRecordZeroArgumentNonVoidMethodPolicy(ZeroArgumentNonVoidMethodPolicy)`.
    - Prevent the method to hide a JavaBeans property (fake or real) of the same name by calling `BeansWrapper.MethodAppearanceDecision.setMethodShadowsProperty(boolean)` with `false`. The default is `true`, so if you have both a property and a method called "foo", then in the template `myObject.foo` will return the method itself instead of the property value, which is often undesirable.
    Parameters:
      `in` - Describes the method about which the decision will be made.
      `out` - Stores how the method will be exposed in the data-model after `process(freemarker.ext.beans.BeansWrapper.MethodAppearanceDecisionInput, freemarker.ext.beans.BeansWrapper.MethodAppearanceDecision)` returns. This is initialized so that it reflects the default behavior of `BeansWrapper`, so you don't have to do anything with this when you don't want to change the default behavior.