public static Set<String> getNecessaryTemplateVariables(String templateName) throws TemplateModelException {
Set<String> result = new HashSet<>();
TemplateElement rootTreeNode = getTemplate(templateName).getRootTreeNode();
if ("IteratorBlock".equals(rootTreeNode.getClass().getSimpleName())) {
introspectFromIteratorBlock(result, rootTreeNode);
return result;
}
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())) {
introspectFromDollarVariable(result, wrappedObject);
} else if ("ConditionalBlock".equals(wrappedObject.getClass().getSimpleName())) {
introspectFromConditionalBlock(result, wrappedObject);
} else if ("IfBlock".equals(wrappedObject.getClass().getSimpleName())) {
introspectFromIfBlock(result, wrappedObject);
} else if ("IteratorBlock".equals(wrappedObject.getClass().getSimpleName())) {
introspectFromIteratorBlock(result, wrappedObject);
}
}
return result;
}
private static void introspectFromIteratorBlock(Set<String> result, Object wrappedObject) {
try {
Object expression = getInternalState(wrappedObject, "listExp");
result.add(getInternalState(expression, "name").toString());
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
}
private static void introspectFromConditionalBlock(Set<String> result, Object wrappedObject)
throws TemplateModelException {
try {
Object expression = getInternalState(wrappedObject, "condition");
if (expression == null) {
return;
}
result.addAll(dealCommonExpression(expression));
String nested = getInternalState(wrappedObject, "nestedBlock").toString();
result.addAll(getNecessaryTemplateVariables(nested));
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
}
private static Set<String> dealCommonExpression(Object expression)
throws NoSuchFieldException, IllegalAccessException {
Set<String> ret = Sets.newHashSet();
switch (expression.getClass().getSimpleName()) {
case "ComparisonExpression":
String reference = dealComparisonExpression(expression);
ret.add(reference);
break;
case "ExistsExpression":
reference = dealExistsExpression(expression);
ret.add(reference);
break;
case "AndExpression":
ret.addAll(dealAndExpression(expression));
default:
break;
}
return ret;
}
private static String dealComparisonExpression(Object expression)
throws NoSuchFieldException, IllegalAccessException {
Object left = getInternalState(expression, "left");
Object right = getInternalState(expression, "right");
String reference;
if ("Identifier".equals(left.getClass().getSimpleName())) {
reference = getInternalState(left, "name").toString();
} else {
reference = getInternalState(right, "name").toString();
}
return reference;
}
private static String dealExistsExpression(Object expression) throws NoSuchFieldException, IllegalAccessException {
Object exp = getInternalState(expression, "exp");
return getInternalState(exp, "name").toString();
}
private static Set<String> dealAndExpression(Object expression) throws NoSuchFieldException,
IllegalAccessException{
Set<String> ret = Sets.newHashSet();
Object lho = getInternalState(expression, "lho");
ret.addAll(dealCommonExpression(lho));
Object rho = getInternalState(expression, "rho");
ret.addAll(dealCommonExpression(rho));
return ret;
}
private static void introspectFromIfBlock(Set<String> result, Object wrappedObject)
throws TemplateModelException {
result.addAll(getNecessaryTemplateVariables(wrappedObject.toString()));
}
private static void introspectFromDollarVariable(Set<String> result, Object wrappedObject)
throws TemplateModelException {
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:
break;
}
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new TemplateModelException("Unable to reflect template model");
}
}
private static Object getInternalState(Object o, String fieldName) throws NoSuchFieldException, IllegalAccessException {
Field [] fieldArray = o.getClass().getDeclaredFields();
for (Field field : fieldArray) {
if (!field.getName().equals(fieldName)) {
continue;
}
boolean wasAccessible = field.isAccessible();
try {
field.setAccessible(true);
return field.get(o);
} finally {
field.setAccessible(wasAccessible);
}
}
throw new NoSuchFieldException();
}
private static Template getTemplate(String templateName) {
try {
StringReader stringReader = new StringReader(templateName);
return new Template(null, stringReader, null);
} catch (IOException e) {
throw new IllegalStateException("Failed to Load Template: " + templateName, e);
}
}
I optimized SimY4 s answer, and supported <#list> and <#if> block. Code is not fully tested