kodeninja
kodeninja

Reputation: 349

Convert Velocity Macro into Java Directive

I'm trying to convert the below velocity macro into a velocity Java directive, as I need to add some bells and whistles around the rendering logic:

#macro(renderModules $modules)
    #if($modules)
        #foreach($module in $modules)
            #if(${module.template})
                #set($moduleData = $module.data)
                #parse("${module.template}.vm")
            #end
        #end
    #end
#end

My equivalent Java Directive:

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.parser.node.ASTBlock;
import org.apache.velocity.runtime.parser.node.Node;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.Writer;
import java.util.List;

public class RenderModulesDirective extends Directive {
    private static final Logger LOGGER = LoggerFactory.getLogger(RenderModulesDirective.class);

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

    @Override
    public int getType() {
        return LINE;
    }

    @Override
    public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {

        for(int i=0; i<node.jjtGetNumChildren(); i++) {
            Node modulesNode = node.jjtGetChild(i);
            if (modulesNode != null) {
                if(!(modulesNode instanceof ASTBlock)) {
                    if(i == 0) {
                        // This should be the list of modules
                        List<Module> modules = (List<Module>) modulesNode.value(context);
                        if(modules != null) {
                            for (Module module : modules) {
                                context.put("moduleData", module.getData());
                                String templateName = module.getTemplate() + ".vm";
                                try {
                                    // ??? How to parse the template here ???
                                } catch(Exception e) {
                                    LOGGER.error("Encountered an error while rendering the Module {}", module, e);
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }

        return true;
    }
}

So, I'm stuck at the point where I need the Java equivalent of the #parse("<template_name>.vm") call. Is this the right approach? Would it help to instead extend from the Parse directive?

Upvotes: 0

Views: 667

Answers (1)

Jay Estrella
Jay Estrella

Reputation: 24

I believe

Template template = Velocity.getTemplate("path/to/template.vm");
template.merge(context, writer);

will accomplish what you're looking to do.

If you have access to RuntimeServices you could call createNewParser() and then call parse(Reader reader, String templateName) inside of the parser, the SimpleNode that comes out has a render() method which I think is what you're looking fo

Upvotes: 1

Related Questions