How can I introspect a freemarker template to find out what variables it uses?

前端 未结 7 573
无人共我
无人共我 2021-01-01 15:27

I\'m not at all sure that this is even a solvable problem, but supposing that I have a freemarker template, I\'d like to be able to ask the template what variables it uses.<

7条回答
  •  一整个雨季
    2021-01-01 15:57

    I had the same task to get the list of variables from template on java side and don't found any good approaches to that except using reflection. I'm not sure whether there is a better way to get this data or not but here's my approach:

    public Set referenceSet(Template template) throws TemplateModelException {
        Set result = new HashSet<>();
        TemplateElement rootTreeNode = template.getRootTreeNode();
        for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
            TemplateModel templateModel = rootTreeNode.getChildNodes().get(i);
            if (!(templateModel instanceof StringModel)) {
                continue;
            }
            Object wrappedObject = ((StringModel) templateModel).getWrappedObject();
            if (!"DollarVariable".equals(wrappedObject.getClass().getSimpleName())) {
                continue;
            }
    
            try {
                Object expression = getInternalState(wrappedObject, "expression");
                switch (expression.getClass().getSimpleName()) {
                    case "Identifier":
                        result.add(getInternalState(expression, "name").toString());
                        break;
                    case "DefaultToExpression":
                        result.add(getInternalState(expression, "lho").toString());
                        break;
                    case "BuiltinVariable":
                        break;
                    default:
                        throw new IllegalStateException("Unable to introspect variable");
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new TemplateModelException("Unable to reflect template model");
            }
        }
        return result;
    }
    
    private Object getInternalState(Object o, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Field field = o.getClass().getDeclaredField(fieldName);
        boolean wasAccessible = field.isAccessible();
        try {
            field.setAccessible(true);
            return field.get(o);
        } finally {
            field.setAccessible(wasAccessible);
        }
    }
    

    Sample project that I made for demonstrating template introspection can be found on github: https://github.com/SimY4/TemplatesPOC.git

提交回复
热议问题