Inheritance / instanceof checks in Freemarker

我的梦境 提交于 2019-12-10 18:09:29

问题


my use case is to provide the user the possibility to create reports with the help of a template engine. Therefore I extracted the relevant part of my data model and integrated Freemarker as template engine. So far it worked great, but now my data model contains inheritance on some positions - but Freemarker does not seem to support instanceof operations? How to deal with this problem? Are there any other template engines which support inheritance in the model?

Fictive example:

I have 2 classes "Car" and "Bike" which extends "Vehicle". And the model contains a class "vehicle fleet" which contains a list of vehicles. User wants ( with the help of a template) to iterate through the list and write in case of a car the attribute "countSeats", in case of a bike the attribute "frame size". How can this be achieved with Freemarker? Can it be done in any template engine?

Many thanks in advance!

// Edit: Unfortunately it's not possible to split the list with the superclasses in several lists with the 'concrete' objects since the order of vehicles (in the above example) within the list is essential.


回答1:


There's nothing built in for this, but it doesn't have to be either. You can write your own TemplateMethodModelEx, or put plain Java helper objects into the data-model to do pretty much anything. Or, you can just put the relevant classes into the data-model, like root.put("Car", Car.class) etc., and then use the Java API of Class like this: <#if Car.isInstance(someObject)>




回答2:


Uglier solution

            <#if yourObject.class.simpleName == "Simple class name like String">
                something
            </#if>                     

            <#if yourObject.class.simpleName == "other simple class name">
                do something else
            </#if>  `



回答3:


Solution using TemplateMethodModelEx.

Class:

public class InstanceOfMethod implements TemplateMethodModelEx {

    @Override
    public Object exec(List list) throws TemplateModelException
    {
        if (list.size() != 2) {
            throw new TemplateModelException("Wrong arguments for method 'instanceOf'. Method has two required parameters: object and class");
        } else {
            Object object = ((WrapperTemplateModel) list.get(0)).getWrappedObject();
            Object p2 = ((WrapperTemplateModel) list.get(1)).getWrappedObject();
            if (!(p2 instanceof Class)) {
                throw new TemplateModelException("Wrong type of the second parameter. It should be Class. Found: " + p2.getClass());
            } else {
                Class c = (Class) p2;
                return c.isAssignableFrom(object.getClass());
            }
        }
    }
}

Put the instance of that class and all required classes to template's input parameters:

parameters.put("instanceOf", new InstanceOfMethod());
parameters.put("Car", Car.class);
...

Or you can add method to shared variables: http://freemarker.org/docs/pgui_config_sharedvariables.html

So you can use the method in FTL as follows:

<#if instanceOf(object, Car)>
       ...
</#if>


来源:https://stackoverflow.com/questions/30416693/inheritance-instanceof-checks-in-freemarker

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!