问题
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