You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by ge...@locus.apache.org on 2000/11/20 00:28:01 UTC
cvs commit: jakarta-velocity/src/java/org/apache/velocity/runtime/directive VelocimacroProxy.java
geirm 00/11/19 15:28:01
Added: src/java/org/apache/velocity/runtime/directive
VelocimacroProxy.java
Log:
Proxy Directive for Velocimacros. Is analagous to Foreach.java, Parse.java. It's job is to patch in the instance-use arguments to the VM, parse the VM, and then render the output using the context.
Revision Changes Path
1.1 jakarta-velocity/src/java/org/apache/velocity/runtime/directive/VelocimacroProxy.java
Index: VelocimacroProxy.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 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", "Tomcat", 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 apache@apache.org.
*
* 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/>.
*/
/**
* VelocimacroProxy.java
*
* a proxy Directive-derived object to fit with the current directive system
*
* @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
* @version $Id: VelocimacroProxy.java,v 1.1 2000/11/19 23:28:00 geirm Exp $
*/
package org.apache.velocity.runtime.directive;
import java.io.Writer;
import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.util.StringTokenizer;
import java.util.Hashtable;
import java.util.TreeMap;
import java.util.Set;
import java.util.Iterator;
import org.apache.velocity.Context;
import org.apache.velocity.runtime.Runtime;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.parser.node.SimpleNode;
public class VelocimacroProxy extends Directive
{
private String strMacroName_ = "";
private String strMacro_ = "";
private String[] strArgArray_ = null;
private String[] strMacroArray_ = null;
private TreeMap tmArgIndexMap_ = null;
private SimpleNode nodeTree_ = null;
public String getName() { return strMacroName_; }
public int getType() { return LINE; }
/**
* sets the directive name of this VM
*/
public void setName( String strName )
{
strMacroName_ = strName;
}
/**
* sets the array of arguments specified in the macro definition
*/
public void setArgArray( String [] strArray )
{
strArgArray_ = strArray;
}
/**
* sets the array of macro elements. (The macro body is an array of token literals..)
* Currently, this isn't used in init or render, but keeping it around if
* someone needs it later.
*/
public void setMacroArray( String [] strArray )
{
strMacroArray_ = strArray;
}
/**
* sets the ArgIndexMap, a map of indexes of macro arg locations in the macro string
* to the argument index. Makes patching the macro really easy.
*/
public void setArgIndexMap( TreeMap tm)
{
tmArgIndexMap_ = tm;
}
/**
* Sets the orignal macro body. This is simply the cat of the strMacroArray, but the
* Macro object creates this once during parsing, and everyone shares it.
* Note : it must not be modified.
*/
public void setMacrobody( String strMacro )
{
strMacro_ = strMacro;
}
/**
* Renders the macro using the context
*/
public boolean render(Context context, Writer writer, Node node)
throws IOException
{
try
{
nodeTree_.render(context, writer );
}
catch ( Exception e )
{
System.out.println("VelocimacroProxy.render() : exception " + e);
Runtime.error("VM error : " + strMacroName_ + " : " + e );
}
return true;
}
/**
* The major meat of VelocimacroProxy, init() checks the # of arguments, patches the
* macro body, renders the macro into an AST, and then inits the AST, so it is ready
* for quick rendering.
*/
public void init(Context context, Node node)
throws Exception
{
/*
* how many args did we get?
*/
int i = node.jjtGetNumChildren();
/*
* get the arg count from the arg array. remember that the arg array
* has the macro name as it's 0th element
* if we don't have enough children specified...?
*/
int iArgCount = strArgArray_.length - 1;
if ( iArgCount != i )
{
Runtime.error("VM : error : too few arguments to macro. Wanted "
+ iArgCount + " got " + i + " -->");
return;
}
/*
* get the argument list to the instance use of the VM
*/
String strCallingArgs[] = getArgArray( node );
/*
* now, expand our macro out to a string patched with the instance arguments
*/
StringBuffer strExpanded = expandMacroArray( strCallingArgs );
/*
* ok. I have the expanded macro.
* now, all I have to do is let the parser render it
*/
try
{
/*
* take the patched macro code, and render() and init()
*/
ByteArrayInputStream inStream = new ByteArrayInputStream( strExpanded.toString().getBytes() );
nodeTree_ = Runtime.parse( inStream );
nodeTree_.init( context, null );
}
catch ( Exception e )
{
System.out.println("VelocimacroProxy.render() : exception " + e);
Runtime.error("VM error : " + strMacroName_ + " : " + e );
}
/*
* we're done. We have the correct AST
*/
return;
}
/**
* gets the args to the VM from the instance-use AST
*/
private String[] getArgArray( Node node )
{
int iNumArgs = node.jjtGetNumChildren();
String strArgs[] = new String[ iNumArgs ];
/*
* eat the args
*/
int i = 0;
while( i < iNumArgs )
{
strArgs[i] = node.jjtGetChild(i).getFirstToken().image;
i++;
}
return strArgs;
}
/**
* expands our macro out given our arg list. Uses
* the pre-created arg index map to run through and patch
* with our args
*/
private StringBuffer expandMacroArray( String [] strCallingArgs )
{
/*
* build the output string by running through the map in sorted order and construct
* the new string. Remember, don't modify the strMacro. Make a new one. The index
* elements are specific to the orignal macro body..
*/
Set set = tmArgIndexMap_.keySet();
Iterator it = set.iterator();
StringBuffer sbNew = new StringBuffer();
int iLoc = 0;
while( it.hasNext() )
{
Integer iIndex = (Integer) it.next();
int iWhich = ((Integer) tmArgIndexMap_.get( iIndex )).intValue();
int iIndexInt = iIndex.intValue();
sbNew.append( strMacro_.substring( iLoc, iIndexInt ));
sbNew.append( strCallingArgs[iWhich - 1] );
iLoc = iIndexInt + strArgArray_[iWhich].length();
}
/*
* and finish off the string
*/
sbNew.append( strMacro_.substring( iLoc ) );
return sbNew;
}
}