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]



Reply via email to