You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@velocity.apache.org by 于世英 <yu...@cgsoft.com.cn> on 2007/07/26 11:59:00 UTC

Need help on write my custom velocity directive

Hi all, 
I'm going to writing some directives to extend Velocity.  now I'm in lacking
of documents. 
I've read the PPT 《Hacking Velocity》by Will Glass-Husain, and some souce
code of system directive such as "literal", "execute", but I don't
understand "foreach" till now. 
I've written the following code(Mydd.java) and it can work as coded now:
-------------------file begin ------------------------------
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;

import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.log4j.Logger;

public class Mydd extends Directive {

	private static Logger logger = Logger.getLogger(Mydd.class);
	
    public void init(RuntimeServices rs, InternalContextAdapter context,
Node node)
        throws TemplateInitException
    {
        super.init(rs, context, node);

    }
	@Override
	public String getName() {
		return "mydd";
	}

	@Override
	public int getType() {

		return LINE;
	}

    public boolean render(InternalContextAdapter context,
                           Writer writer, Node node) throws IOException
    {
    	for (int i = 0; i < node.jjtGetNumChildren(); i ++) {
    		logger.debug("debug mydd parameter: " + node.jjtGetChild(i).
toString() + " (" + node.jjtGetChild(i).literal() + ")");
    	}
    	writer.write("Hello, world!");
        return true;
    }
}
-------------------file end ----------------------------------

What I want to know is:
1, the above directive's syntax in template is 
#mydd(arg1 arg2 arg3 ...)
but system directives like "foreach" and "set" have COOL syntax like
"#foreach ($a in $set)", how to let my directive support syntax like this?
2, does the directive mechanism provided Velocity has other convenience or
power that I don't know ? what I know about  is all in the above code :-)

Thanks in advance, any hint will be appreciated!


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: Need help on write my custom velocity directive

Posted by Nathan Bubna <nb...@gmail.com>.
On 7/26/07, 于世英 <yu...@cgsoft.com.cn> wrote:
> Hi all,
> I'm going to writing some directives to extend Velocity.  now I'm in lacking
> of documents.
> I've read the PPT 《Hacking Velocity》by Will Glass-Husain, and some souce
> code of system directive such as "literal", "execute", but I don't
> understand "foreach" till now.
> I've written the following code(Mydd.java) and it can work as coded now:
> -------------------file begin ------------------------------
> import java.io.IOException;
> import java.io.Writer;
> import java.util.Iterator;
>
> import org.apache.velocity.context.InternalContextAdapter;
> import org.apache.velocity.exception.MethodInvocationException;
> import org.apache.velocity.exception.ParseErrorException;
> import org.apache.velocity.exception.ResourceNotFoundException;
> import org.apache.velocity.runtime.directive.Directive;
> import org.apache.velocity.runtime.RuntimeServices;
> import org.apache.velocity.runtime.parser.node.Node;
> import org.apache.velocity.exception.TemplateInitException;
> import org.apache.log4j.Logger;
>
> public class Mydd extends Directive {
>
>         private static Logger logger = Logger.getLogger(Mydd.class);
>
>     public void init(RuntimeServices rs, InternalContextAdapter context,
> Node node)
>         throws TemplateInitException
>     {
>         super.init(rs, context, node);
>
>     }
>         @Override
>         public String getName() {
>                 return "mydd";
>         }
>
>         @Override
>         public int getType() {
>
>                 return LINE;
>         }
>
>     public boolean render(InternalContextAdapter context,
>                            Writer writer, Node node) throws IOException
>     {
>         for (int i = 0; i < node.jjtGetNumChildren(); i ++) {
>                 logger.debug("debug mydd parameter: " + node.jjtGetChild(i).
> toString() + " (" + node.jjtGetChild(i).literal() + ")");
>         }
>         writer.write("Hello, world!");
>         return true;
>     }
> }
> -------------------file end ----------------------------------
>
> What I want to know is:
> 1, the above directive's syntax in template is
> #mydd(arg1 arg2 arg3 ...)
> but system directives like "foreach" and "set" have COOL syntax like
> "#foreach ($a in $set)", how to let my directive support syntax like this?

IIRC, those core directives all have special privileges via parsing
code and other stuff.  You'll probably have to modify the JavaCC
grammar and rebuild the velocity.jar to achieve similar results.

> 2, does the directive mechanism provided Velocity has other convenience or
> power that I don't know ? what I know about  is all in the above code :-)

i'm not sure.  Will might know better than me on this.  You can also
explore what other custom directives do for ideas.  I believe there
are a few in the contributed code of the wiki and in the whiteboard
area of the source (via either SVN or the source distro).  Also,
Struts 2 uses custom directives pretty extensively.  With direct
access to the AST (via the Node), i'm sure there's quite a lot that
can be done.

>
> Thanks in advance, any hint will be appreciated!
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
For additional commands, e-mail: user-help@velocity.apache.org


Re: Need help on write my custom velocity directive

Posted by Will Glass-Husain <wg...@gmail.com>.
Hi,

The system directives are treated a little differently.  The parser
recognizes them and does some syntax checking at compile time.  (See "
parser.jjt").

As far as user directives, you can check the argument nodes for specific
types (strings, references, etc) and throw an exception if they are
invalid.  For example, require the first and third arguments to be
references.  Matching "in" is a bit of a problem since it's not generic
syntax.  (e.g. it's not a literal or a reference).

WILL


On 7/26/07, 于世英 <yu...@cgsoft.com.cn> wrote:
>
> Hi all,
> I'm going to writing some directives to extend Velocity.  now I'm in
> lacking
> of documents.
> I've read the PPT 《Hacking Velocity》by Will Glass-Husain, and some souce
> code of system directive such as "literal", "execute", but I don't
> understand "foreach" till now.
> I've written the following code(Mydd.java) and it can work as coded now:
> -------------------file begin ------------------------------
> import java.io.IOException;
> import java.io.Writer;
> import java.util.Iterator;
>
> import org.apache.velocity.context.InternalContextAdapter;
> import org.apache.velocity.exception.MethodInvocationException;
> import org.apache.velocity.exception.ParseErrorException;
> import org.apache.velocity.exception.ResourceNotFoundException;
> import org.apache.velocity.runtime.directive.Directive;
> import org.apache.velocity.runtime.RuntimeServices;
> import org.apache.velocity.runtime.parser.node.Node;
> import org.apache.velocity.exception.TemplateInitException;
> import org.apache.log4j.Logger;
>
> public class Mydd extends Directive {
>
>         private static Logger logger = Logger.getLogger(Mydd.class);
>
>     public void init(RuntimeServices rs, InternalContextAdapter context,
> Node node)
>         throws TemplateInitException
>     {
>         super.init(rs, context, node);
>
>     }
>         @Override
>         public String getName() {
>                 return "mydd";
>         }
>
>         @Override
>         public int getType() {
>
>                 return LINE;
>         }
>
>     public boolean render(InternalContextAdapter context,
>                            Writer writer, Node node) throws IOException
>     {
>         for (int i = 0; i < node.jjtGetNumChildren(); i ++) {
>                 logger.debug("debug mydd parameter: " + node.jjtGetChild
> (i).
> toString() + " (" + node.jjtGetChild(i).literal() + ")");
>         }
>         writer.write("Hello, world!");
>         return true;
>     }
> }
> -------------------file end ----------------------------------
>
> What I want to know is:
> 1, the above directive's syntax in template is
> #mydd(arg1 arg2 arg3 ...)
> but system directives like "foreach" and "set" have COOL syntax like
> "#foreach ($a in $set)", how to let my directive support syntax like this?
> 2, does the directive mechanism provided Velocity has other convenience or
> power that I don't know ? what I know about  is all in the above code :-)
>
> Thanks in advance, any hint will be appreciated!
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
> For additional commands, e-mail: user-help@velocity.apache.org
>
>


-- 
Forio Business Simulations

Will Glass-Husain
wglass@forio.com
www.forio.com