I'm thinking of working with Template.parse() to locate/detect any and all plain text in a large set of existng templates. Has anyone else done anything like this? Any pointers or anything in the tools that might give a jumpstart on this?
Thanks -----Original Message----- From: marvin greenberg [mailto:[EMAIL PROTECTED] Sent: Saturday, March 01, 2003 7:43 AM To: Velocity Users List Cc: [EMAIL PROTECTED] Subject: Re: improvements (perhaps) to TemplateTool OK, I finally got back to doing interesting things (as opposed to what I get paid for). I modified G. Magnusson's template tool to display equivalent forms only once (except that $Fred and ${Fred} still generate separate references -- there is an easy fix but there is still a related bug that I need to look at when I get a chance so I'm leaving it for now). It also gives a summary for all files passed (or only gives a summary if -s is specified). I've attached the source at the bottom. I want to make this "architecturally more proper" -- right now its a bit of hack. Sample call: java TemplateTool templates/Node/InterfaceNode/*.vm File: templates/Node/InterfaceNode/Type.cpp.vm templateFileName this.Name File: templates/Node/InterfaceNode/Type.h.vm $OMname $templateFileName $this.Name $this.Name.toPath( 0 args ) $this.isClass( 0 args ) $util.toDefineName( 1 args ) OMname this.Name.Base util.toDefineName( 1 args ) File: templates/Node/InterfaceNode/Type.i.vm $templateFileName $this.Name $this.Name.toQualifiedName( 0 args ) Summary: $OMname $templateFileName $this.Name $this.Name.toPath( 0 args ) $this.isClass( 0 args ) $this.Name.toQualifiedName( 0 args ) $util.toDefineName( 1 args ) OMname this.Name this.Name.Base util.toDefineName( 1 args ) On Thu, 2003-02-06 at 15:23, Marvin Greenberg wrote: > I've made some minor changes to the template tool. I got rid of the stuff > that listed every (including repeat) reference, and changed it so that > references are listed in a sorted order, and that a summary for all the > template files is also generated. I also plan to add an option to make all > equivalent forms show up only once -- $class.Name and ${class.Name} and > $class.getName(), and compress methods references to only the name and arg > count. Beyond that I was thinking about a doclet to generate a bean > description from a java class or set of classes (something exists perhaps?), > which could then be used to actually validate the templates. --------------------------------------------------------------------------- /* * The Apache Software License, Version 1.1 * * Copyright (c) 2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Velocity", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ import java.util.ArrayList; import java.util.TreeSet; import java.util.Set; import java.util.List; import java.util.Iterator; import java.io.File; import org.apache.velocity.Template; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.parser.node.SimpleNode; import org.apache.velocity.runtime.parser.node.ASTReference; import org.apache.velocity.runtime.visitor.BaseVisitor; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.runtime.parser.ParserConstants; import org.apache.velocity.runtime.parser.Token; /** * * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a> * @author Marvin Greenberg * @version $Id: $ */ public class TemplateTool { /** List references in template refered to by file referred to by String fn */ public TemplateTool( VelocityEngine ve, String fn ) throws Exception { this( ve.getTemplate( fn ) ); } public TemplateTool( Template t ) { _template = t; } /* returns null if no valid template */ public Set getReferences() { if (null == _template) return null; SimpleNode sn = (SimpleNode) _template.getData(); ReferenceListVisitor rlv = new ReferenceListVisitor(); sn.jjtAccept( rlv, null ); return rlv.getReferences(); } private Template _template; public static void usage() { System.err.println("java TemplateTool [-s | --summarize] templatefile..."); System.exit(1); } public static void main( String args[] ) throws Exception { List files = new ArrayList(); boolean summarize = false; boolean error = false; for (int i=0; i<args.length; ++i) { if ("-s".equals(args[i]) || "--summarize".equals(args[i])) { summarize = true; } else { File f = new File(args[i]); if (f.isFile()) files.add(args[i]); else { System.err.println("Ignored: " + args[i] + ": invalid flag or nonexistent file"); error = true; } } } if (error) usage(); VelocityEngine ve = new VelocityEngine(); ve.init(); Set summary = new TreeSet(); for (Iterator fiter = files.iterator(); fiter.hasNext(); ) { String fn = (String)fiter.next(); try { Set refs = (new TemplateTool( ve, fn )).getReferences(); if (!summarize) { System.out.println("\nFile: " + fn ); for (Iterator iter = refs.iterator(); iter.hasNext(); ) { System.out.println("\t" + iter.next() ); } } summary.addAll( refs ); } catch (Exception e) { System.err.println("In " + fn + ":\n" + e); } } /* Summarize if there was more than one template */ if (files.size() > 1) { System.out.println("\n\nSummary: " ); for (Iterator iter = summary.iterator(); iter.hasNext(); ) { System.out.println("\t" + iter.next() ); } } } /** * Visitor to accumulate references. */ class ReferenceListVisitor extends BaseVisitor { Set _refset = null; ReferenceListVisitor() { _refset = new TreeSet(); // So references get expected ordering } public Set getReferences() { return _refset; } /** handle the resolution of arguments into an arg count, and * resolve getProperty( 0 args ) to Property. Similarly should * change setProperty( 1 args ) to Property = , but there are unresolved * issues about this since aren't reporting other assignments yet... * * @param boolean isMethod True if processing a method token * @param Token[] tokenRef Use a 1 element array to allow modification of the tokenRef * @param Token the last Token that is part of the current expression */ private StringBuffer handleExpression ( boolean isMethod, Token[] tokenRef, Token lastToken) { Token name = null; if (isMethod) { name = tokenRef[0]; tokenRef[0] = tokenRef[0].next; } StringBuffer sb = new StringBuffer(); boolean nodeConsumed = false; int argCount = 0; int discardAll = 0; // throw away contents of arrays -- just count as an argument for (; tokenRef[0] != null && ! nodeConsumed; tokenRef[0] = tokenRef[0].next ) { switch (tokenRef[0].kind) { case ParserConstants.LBRACKET: if (isMethod && discardAll==0) ++ argCount; ++discardAll; break; case ParserConstants.RBRACKET: --discardAll; break; case ParserConstants.LPAREN: case ParserConstants.LCURLY: case ParserConstants.RCURLY: case ParserConstants.DOLLAR: case ParserConstants.DOLLARBANG: case ParserConstants.COMMA: /* do nothing - discard redundant syntax */ break; case ParserConstants.DOT: if (0 == discardAll) sb.append( '.' ); break; case ParserConstants.STRING_LITERAL: if (0 == discardAll) { if (isMethod) ++ argCount; } break; case ParserConstants.IDENTIFIER: if (0 == discardAll) { if (isMethod) ++argCount; // recurse for a method call, so arg count is not messed up if (tokenRef[0].next != null && tokenRef[0].next.kind == ParserConstants.LPAREN) { // handle nested method calls, but just throw away results // except at top, since only care about arg count. // These calls will/should get visited themselves later... StringBuffer methodRef = handleExpression(true, tokenRef, lastToken); if (!isMethod) sb.append(methodRef); } else { // append plain reference sb.append(tokenRef[0].image); } } break; // rparen means return from recursion // For some reason not just RPAREN... case ParserConstants.REFMOD2_RPAREN: if (0 == discardAll) { if (isMethod) { if (argCount == 0 && name.image.startsWith("get") && name.image.length() > 3) sb.append(name.image.substring(3)); else sb.append(name.image); sb.append("( ").append(argCount).append(" args )"); return sb; } } break; default: System.err.println("Discarding some unexpected syntax: " + tokenRef[0].image); } nodeConsumed = (tokenRef[0] == lastToken); } return sb; } public Object visit( ASTReference node, Object data) { Token lastToken = node.getLastToken(); Token[] tokenRef = new Token[] { node.getFirstToken() }; _refset.add( handleExpression( false, tokenRef, lastToken ).toString() ); data = node.childrenAccept(this, data); return data; } } } --------------------------------------------------------------------- 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]
