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]