Howdy folks - I'm wondering how I might limit the comparisons in velocity templates to only boolean conditions.
For example: #if ($value > 20) HIGHLIGHTED BUTTON #else stdbutton #end would throw an exception and would need to be written with a context containing "IS_OVER_LIMIT", new Boolean() and this template: #if ($IS_OVER_LIMIT) HIGHLIGHTED BUTTON #else stdbutton #end
Another example: #if ($widget.size == "LARGE") large #else not large #end would throw an exception and would need to be written as: #if ($widget.size.isLarge()) large #else not large #end
The question here is academic at this point. I do not care to argue
about why this might be good/bad/weird, nor do I want to hear how it
could be done in another engine.
<LOL>
Yeah, you anticipated it. The template engine that cannot be named does work the way you want. The condition in an if must be a bona fide boolean. It doesn't coerce non-empty strings and whatnot into true etcetera. If the thing's not a boolean, it throws.
I'm just curious to know how one might go about messing with Velocity to alter it's behaviour as described. Maybe I'll learn something in the process of looking. :-)
You're in luck, Tim. I have actually been in the Velocity code to write the Velocity->FM template converter. The converter is actually a patched version of Velocity that builds up the tree using Velocity code and then dumps it in FreeMarker syntax.
So I know my around a bit.
The key API to look at is:
boolean org.apache.velocity.runtime.parser.Node.evaluate(InternalContextAdapter context);
This is the hook that is used to evaluate a node in the boolean if context.
To get the stricter behavior you want, you would do 2 things:
1. Patch the evaluate() method on line 334 of org/apache/velocity/runtime/parser/ASTReference.java so that it only accepts boolean values. As follows:
public boolean evaluate( InternalContextAdapter context)
throws MethodInvocationException
{
Object value = execute(null, context);if (value == null)
{
throw new MethodInvocationException("Invalid reference");
}
else if (value instanceof Boolean)
{
if (((Boolean) value).booleanValue())
return true;
else
return false;
}
else
return throw new MethodInvocationException("Cannot do a boolean evaluation of a non-boolean expression");
}
2. Modify the evaluate() method on line 253 of org/apache/velocity/runtime/parser/SimpleNode.java
so that, instead of returning false there, it throws and exception. I guess it should throw MethodInvocationException, as in:
public boolean evaluate(InternalContextAdapter context)
{
// return false; // Comment out.
throw new MethodInvocationException("Cannot do a boolean evaluation of a non-boolean expression");
}
Then recompile and you should have the semantics you want.
Thanks!
You're welcome. You've got to love it when the best available authority on the Velocity code base is...
Yours truly,
Jonathan Revusky
--
lead developer, FreeMarker project, http://freemarker.org/
Velocity->FreeMarker template conversion tool, http.//freemarker.org/usCavalry.html
P.S. Or just use the unnameable template engine. It already works the way you want. :-)
Timo
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
