A dynamic call of a parameter-given name is a minimal parsing, but
still is, preventing any kind of "compile-time linkage" from being
done.
The "expression" seems to be known only at template-parsing-time,
isn't it ?
I think
#call('render'+$component.type $component)
makes very little difference with
#evaluate('#render' + $component.type + '($component)')
If the evaluate directive really performs poorly, then maybe it
should be a good idea to speed it up other than create a new and
specialized one ?
-----Message d'origine-----
De : Adrian Tarau [mailto:[EMAIL PROTECTED] Envoyé : mardi
19
février 2008 16:14
À : Velocity Developers List
Objet : Re: Call a velocity macro
Velocity.evaluate or Velocity.invokeVelocimacro(which calls
evaluate) doesn't provide support to pass objects as parameters
and
is not suitable to be called from a template.
The new directive #evaluate is actually Velocity.evaluate. It is
still an evaluate, which means expression parsing. I would like to
avoid that. If you will call "call/invoke" directive too often I
think it will perform badly, due the fact that a parsing step is
performed.
In this case, a call to a velocity macro, we don't need the
parsing
step. We know the "expression", and what we need is to prepare the
node without parsing.I don't know much about the velocity
internals,
but I presume it should be possible.
And I think such a directive should be part of the core, I mean it
will be easy to implement a "switch"(is what I need actually)
based
on some variable. Like in my case :
#macro(renderLabel $component)
....
#end
#macro(renderTextField $component)
....
#end
#macro(renderRadioButton $component)
....
#end
.....
#call('render'+$component.type $component)
where 'type' is 'label', 'text-field', 'radio-button'(of course
there is a normalization of the type value, first character upper
case, '-' makes the next character uppercase, etc).
Instead of lots of tests with #if, it will be better(and faster)
to
have this 'switch'.At least it looks better, the template is
cleaner
and it is (it will be)also faster.
Thanks.
/Reader reader = *new* BufferedReader(*new*
StringReader(sourceText));
String templateName = context.getCurrentTemplateName();
SimpleNode nodeTree = *null*;
*try*
{
*nodeTree* = rsvc.parse(reader, templateName);
}
*catch* (ParseException pex)
{
//// use the line/column from the template
Info info = *new* Info( templateName, node.getLine(),
node.getColumn() );
*throw* *new* ParseErrorException( pex.getMessage(),
info );
}
*catch* (TemplateInitException pex)
{
Info info = *new* Info( templateName, node.getLine(),
node.getColumn() );
*throw* *new* ParseErrorException( pex.getMessage(),
info );
}/
Massip, Etienne wrote:
Hello
Take a look at the actual RenderTool
(http://velocity.apache.org/tools/releases/1.4/generic/RenderTool.html
).
Or at the new evaluate directive, although still in developement
(http://velocity.apache.org/engine/devel/vtl-reference-guide.html#aevaluate_-_dynamically_evaluates_a_string_or_reference
).
Etienne
-----Message d'origine-----
De : Adrian Tarau [mailto:[EMAIL PROTECTED] Envoyé :
mardi 19
février 2008 07:29 À : dev@velocity.apache.org Objet : Call a
velocity macro
Hello,
I have the following problem : I would like to call a macro but
the
macro name must be a variable.
Ex: instead of #renderLabel($component) to have
#call("renderLabel"
$component) - of course "renderLabel" can be any (existing) macro
name.
I started to create a directive #call, but of course the render
method fails because the nodeTree is not initialized. nodeTree is
initialized during parsing like this
public class ASTDirective extends SimpleNode {
...
directive = rsvc.getVelocimacro( directiveName,
context.getCurrentTemplateName());
try
{
directive.init( rsvc, context, this );
}
..
{
Any thoughts? I think such a directive is very useful, I don't
know
why is not part of the library.
Thanks.
CallDirective source code :
public class CallDirective extends Directive {
public String getName() {
return "call";
}
public int getType() {
return LINE;
}
public boolean render(InternalContextAdapter context, Writer
writer, Node node) throws IOException, ResourceNotFoundException,
ParseErrorException, MethodInvocationException {
if (node.jjtGetNumChildren() < 1) {
rsvc.error("#" + getName() + " : invalid number of
parameters, must be at least the macro name and 0..N
parameters");
return false;
}
String macroName = (String)
node.jjtGetChild(0).value(context);
VelocimacroProxy velocimacro = (VelocimacroProxy)
rsvc.getVelocimacro(macroName, context.getCurrentTemplateName());
if (velocimacro == null) {
rsvc.error("A macro with name '" + macroName + " in
context '" +
context.getCurrentTemplateName() + "' doesn't exists");
return false;
}
return velocimacro.render(context, writer, node);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]