You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by wg...@apache.org on 2007/03/31 22:51:52 UTC
svn commit: r524478 [2/3] - in /velocity/anakia/trunk: ./ build/ src/
src/java/ src/java/org/ src/java/org/apache/ src/java/org/apache/anakia/
src/test/ src/test/org/ src/test/org/apache/ src/test/org/apache/anakia/
src/test/org/apache/anakia/test/ tes...
Added: velocity/anakia/trunk/src/java/org/apache/anakia/AnakiaTask.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/AnakiaTask.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/AnakiaTask.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/AnakiaTask.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,645 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.commons.collections.ExtendedProperties;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.MatchingTask;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.util.StringUtils;
+
+import org.jdom.Document;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.Format;
+import org.xml.sax.SAXParseException;
+
+/**
+ * The purpose of this Ant Task is to allow you to use
+ * Velocity as an XML transformation tool like XSLT is.
+ * So, instead of using XSLT, you will be able to use this
+ * class instead to do your transformations. It works very
+ * similar in concept to Ant's <style> task.
+ * <p>
+ * You can find more documentation about this class on the
+ * Velocity
+ * <a href="http://velocity.apache.org/engine/devel/docs/anakia.html">Website</a>.
+ *
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @version $Id$
+ */
+public class AnakiaTask extends MatchingTask
+{
+ /** <code>{@link SAXBuilder}</code> instance to use */
+ SAXBuilder builder;
+
+ /** the destination directory */
+ private File destDir = null;
+
+ /** the base directory */
+ File baseDir = null;
+
+ /** the style= attribute */
+ private String style = null;
+
+ /** last modified of the style sheet */
+ private long styleSheetLastModified = 0;
+
+ /** the projectFile= attribute */
+ private String projectAttribute = null;
+
+ /** the File for the project.xml file */
+ private File projectFile = null;
+
+ /** last modified of the project file if it exists */
+ private long projectFileLastModified = 0;
+
+ /** check the last modified date on files. defaults to true */
+ private boolean lastModifiedCheck = true;
+
+ /** the default output extension is .html */
+ private String extension = ".html";
+
+ /** the template path */
+ private String templatePath = null;
+
+ /** the file to get the velocity properties file */
+ private File velocityPropertiesFile = null;
+
+ /** the VelocityEngine instance to use */
+ private VelocityEngine ve = new VelocityEngine();
+
+ /** the Velocity subcontexts */
+ private List contexts = new LinkedList();
+
+ /**
+ * Constructor creates the SAXBuilder.
+ */
+ public AnakiaTask()
+ {
+ builder = new SAXBuilder();
+ builder.setFactory(new AnakiaJDOMFactory());
+ }
+
+ /**
+ * Set the base directory.
+ * @param dir
+ */
+ public void setBasedir(File dir)
+ {
+ baseDir = dir;
+ }
+
+ /**
+ * Set the destination directory into which the VSL result
+ * files should be copied to
+ * @param dir the name of the destination directory
+ */
+ public void setDestdir(File dir)
+ {
+ destDir = dir;
+ }
+
+ /**
+ * Allow people to set the default output file extension
+ * @param extension
+ */
+ public void setExtension(String extension)
+ {
+ this.extension = extension;
+ }
+
+ /**
+ * Allow people to set the path to the .vsl file
+ * @param style
+ */
+ public void setStyle(String style)
+ {
+ this.style = style;
+ }
+
+ /**
+ * Allow people to set the path to the project.xml file
+ * @param projectAttribute
+ */
+ public void setProjectFile(String projectAttribute)
+ {
+ this.projectAttribute = projectAttribute;
+ }
+
+ /**
+ * Set the path to the templates.
+ * The way it works is this:
+ * If you have a Velocity.properties file defined, this method
+ * will <strong>override</strong> whatever is set in the
+ * Velocity.properties file. This allows one to not have to define
+ * a Velocity.properties file, therefore using Velocity's defaults
+ * only.
+ * @param templatePath
+ */
+
+ public void setTemplatePath(File templatePath)
+ {
+ try
+ {
+ this.templatePath = templatePath.getCanonicalPath();
+ }
+ catch (java.io.IOException ioe)
+ {
+ throw new BuildException(ioe);
+ }
+ }
+
+ /**
+ * Allow people to set the path to the velocity.properties file
+ * This file is found relative to the path where the JVM was run.
+ * For example, if build.sh was executed in the ./build directory,
+ * then the path would be relative to this directory.
+ * This is optional based on the setting of setTemplatePath().
+ * @param velocityPropertiesFile
+ */
+ public void setVelocityPropertiesFile(File velocityPropertiesFile)
+ {
+ this.velocityPropertiesFile = velocityPropertiesFile;
+ }
+
+ /**
+ * Turn on/off last modified checking. by default, it is on.
+ * @param lastmod
+ */
+ public void setLastModifiedCheck(String lastmod)
+ {
+ if (lastmod.equalsIgnoreCase("false") || lastmod.equalsIgnoreCase("no")
+ || lastmod.equalsIgnoreCase("off"))
+ {
+ this.lastModifiedCheck = false;
+ }
+ }
+
+ /**
+ * Main body of the application
+ * @throws BuildException
+ */
+ public void execute () throws BuildException
+ {
+ DirectoryScanner scanner;
+ String[] list;
+
+ if (baseDir == null)
+ {
+ baseDir = project.resolveFile(".");
+ }
+ if (destDir == null )
+ {
+ String msg = "destdir attribute must be set!";
+ throw new BuildException(msg);
+ }
+ if (style == null)
+ {
+ throw new BuildException("style attribute must be set!");
+ }
+
+ if (velocityPropertiesFile == null)
+ {
+ velocityPropertiesFile = new File("velocity.properties");
+ }
+
+ /*
+ * If the props file doesn't exist AND a templatePath hasn't
+ * been defined, then throw the exception.
+ */
+ if ( !velocityPropertiesFile.exists() && templatePath == null )
+ {
+ throw new BuildException ("No template path and could not " +
+ "locate velocity.properties file: " +
+ velocityPropertiesFile.getAbsolutePath());
+ }
+
+ log("Transforming into: " + destDir.getAbsolutePath(), Project.MSG_INFO);
+
+ // projectFile relative to baseDir
+ if (projectAttribute != null && projectAttribute.length() > 0)
+ {
+ projectFile = new File(baseDir, projectAttribute);
+ if (projectFile.exists())
+ {
+ projectFileLastModified = projectFile.lastModified();
+ }
+ else
+ {
+ log ("Project file is defined, but could not be located: " +
+ projectFile.getAbsolutePath(), Project.MSG_INFO );
+ projectFile = null;
+ }
+ }
+
+ Document projectDocument = null;
+ try
+ {
+ if ( velocityPropertiesFile.exists() )
+ {
+ String file = velocityPropertiesFile.getAbsolutePath();
+ ExtendedProperties config = new ExtendedProperties(file);
+ ve.setExtendedProperties(config);
+ }
+
+ // override the templatePath if it exists
+ if (templatePath != null && templatePath.length() > 0)
+ {
+ ve.setProperty( RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
+ templatePath);
+ }
+
+ ve.init();
+
+ // get the last modification of the VSL stylesheet
+ styleSheetLastModified = ve.getTemplate( style ).getLastModified();
+
+ // Build the Project file document
+ if (projectFile != null)
+ {
+ projectDocument = builder.build(projectFile);
+ }
+ }
+ catch (Exception e)
+ {
+ log("Error: " + e.toString(), Project.MSG_INFO);
+ throw new BuildException(e);
+ }
+
+ // find the files/directories
+ scanner = getDirectoryScanner(baseDir);
+
+ // get a list of files to work on
+ list = scanner.getIncludedFiles();
+ for (int i = 0;i < list.length; ++i)
+ {
+ process(list[i], projectDocument );
+ }
+
+ }
+
+ /**
+ * Process an XML file using Velocity
+ */
+ private void process(String xmlFile, Document projectDocument)
+ throws BuildException
+ {
+ File outFile=null;
+ File inFile=null;
+ Writer writer = null;
+ try
+ {
+ // the current input file relative to the baseDir
+ inFile = new File(baseDir,xmlFile);
+ // the output file relative to basedir
+ outFile = new File(destDir,
+ xmlFile.substring(0,
+ xmlFile.lastIndexOf('.')) + extension);
+
+ // only process files that have changed
+ if (lastModifiedCheck == false ||
+ (inFile.lastModified() > outFile.lastModified() ||
+ styleSheetLastModified > outFile.lastModified() ||
+ projectFileLastModified > outFile.lastModified() ||
+ userContextsModifed(outFile.lastModified())))
+ {
+ ensureDirectoryFor( outFile );
+
+ //-- command line status
+ log("Input: " + xmlFile, Project.MSG_INFO );
+
+ // Build the JDOM Document
+ Document root = builder.build(inFile);
+
+ // Shove things into the Context
+ VelocityContext context = new VelocityContext();
+
+ /*
+ * get the property TEMPLATE_ENCODING
+ * we know it's a string...
+ */
+ String encoding = (String) ve.getProperty( RuntimeConstants.OUTPUT_ENCODING );
+ if (encoding == null || encoding.length() == 0
+ || encoding.equals("8859-1") || encoding.equals("8859_1"))
+ {
+ encoding = "ISO-8859-1";
+ }
+
+ Format f = Format.getRawFormat();
+ f.setEncoding(encoding);
+
+ OutputWrapper ow = new OutputWrapper(f);
+
+ context.put ("root", root.getRootElement());
+ context.put ("xmlout", ow );
+ context.put ("relativePath", getRelativePath(xmlFile));
+ context.put ("treeWalk", new TreeWalker());
+ context.put ("xpath", new XPathTool() );
+ context.put ("escape", new Escape() );
+ context.put ("date", new java.util.Date() );
+
+ /**
+ * only put this into the context if it exists.
+ */
+ if (projectDocument != null)
+ {
+ context.put ("project", projectDocument.getRootElement());
+ }
+
+ /**
+ * Add the user subcontexts to the to context
+ */
+ for (Iterator iter = contexts.iterator(); iter.hasNext();)
+ {
+ Context subContext = (Context) iter.next();
+ if (subContext == null)
+ {
+ throw new BuildException("Found an undefined SubContext!");
+ }
+
+ if (subContext.getContextDocument() == null)
+ {
+ throw new BuildException("Could not build a subContext for " + subContext.getName());
+ }
+
+ context.put(subContext.getName(), subContext
+ .getContextDocument().getRootElement());
+ }
+
+ /**
+ * Process the VSL template with the context and write out
+ * the result as the outFile.
+ */
+ writer = new BufferedWriter(new OutputStreamWriter(
+ new FileOutputStream(outFile),
+ encoding));
+
+ /**
+ * get the template to process
+ */
+ Template template = ve.getTemplate(style);
+ template.merge(context, writer);
+
+ log("Output: " + outFile, Project.MSG_INFO );
+ }
+ }
+ catch (JDOMException e)
+ {
+ outFile.delete();
+
+ if (e.getCause() != null)
+ {
+ Throwable rootCause = e.getCause();
+ if (rootCause instanceof SAXParseException)
+ {
+ System.out.println("");
+ System.out.println("Error: " + rootCause.getMessage());
+ System.out.println(
+ " Line: " +
+ ((SAXParseException)rootCause).getLineNumber() +
+ " Column: " +
+ ((SAXParseException)rootCause).getColumnNumber());
+ System.out.println("");
+ }
+ else
+ {
+ rootCause.printStackTrace();
+ }
+ }
+ else
+ {
+ e.printStackTrace();
+ }
+ }
+ catch (Throwable e)
+ {
+ if (outFile != null)
+ {
+ outFile.delete();
+ }
+ e.printStackTrace();
+ }
+ finally
+ {
+ if (writer != null)
+ {
+ try
+ {
+ writer.flush();
+ }
+ catch (IOException e)
+ {
+ // Do nothing
+ }
+
+ try
+ {
+ writer.close();
+ }
+ catch (IOException e)
+ {
+ // Do nothing
+ }
+ }
+ }
+ }
+
+ /**
+ * Hacky method to figure out the relative path
+ * that we are currently in. This is good for getting
+ * the relative path for images and anchor's.
+ */
+ private String getRelativePath(String file)
+ {
+ if (file == null || file.length()==0)
+ return "";
+ StringTokenizer st = new StringTokenizer(file, "/\\");
+ // needs to be -1 cause ST returns 1 even if there are no matches. huh?
+ int slashCount = st.countTokens() - 1;
+ StringBuffer sb = new StringBuffer();
+ for (int i=0;i<slashCount ;i++ )
+ {
+ sb.append ("../");
+ }
+
+ if (sb.toString().length() > 0)
+ {
+ return StringUtils.chop(sb.toString(), 1);
+ }
+
+ return ".";
+ }
+
+ /**
+ * create directories as needed
+ */
+ private void ensureDirectoryFor( File targetFile ) throws BuildException
+ {
+ File directory = new File( targetFile.getParent() );
+ if (!directory.exists())
+ {
+ if (!directory.mkdirs())
+ {
+ throw new BuildException("Unable to create directory: "
+ + directory.getAbsolutePath() );
+ }
+ }
+ }
+
+
+ /**
+ * Check to see if user context is modified.
+ */
+ private boolean userContextsModifed(long lastModified)
+ {
+ for (Iterator iter = contexts.iterator(); iter.hasNext();)
+ {
+ AnakiaTask.Context ctx = (AnakiaTask.Context) iter.next();
+ if(ctx.getLastModified() > lastModified)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Create a new context.
+ * @return A new context.
+ */
+ public Context createContext()
+ {
+ Context context = new Context();
+ contexts.add(context);
+ return context;
+ }
+
+
+ /**
+ * A context implementation that loads all values from an XML file.
+ */
+ public class Context
+ {
+
+ private String name;
+ private Document contextDoc = null;
+ private String file;
+
+ /**
+ * Public constructor.
+ */
+ public Context()
+ {
+ }
+
+ /**
+ * Get the name of the context.
+ * @return The name of the context.
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Set the name of the context.
+ * @param name
+ *
+ * @throws IllegalArgumentException if a reserved word is used as a
+ * name, specifically any of "relativePath", "treeWalk", "xpath",
+ * "escape", "date", or "project"
+ */
+ public void setName(String name)
+ {
+ if (name.equals("relativePath") ||
+ name.equals("treeWalk") ||
+ name.equals("xpath") ||
+ name.equals("escape") ||
+ name.equals("date") ||
+ name.equals("project"))
+ {
+
+ throw new IllegalArgumentException("Context name '" + name
+ + "' is reserved by Anakia");
+ }
+
+ this.name = name;
+ }
+
+ /**
+ * Build the context based on a file path.
+ * @param file
+ */
+ public void setFile(String file)
+ {
+ this.file = file;
+ }
+
+ /**
+ * Retrieve the time the source file was last modified.
+ * @return The time the source file was last modified.
+ */
+ public long getLastModified()
+ {
+ return new File(baseDir, file).lastModified();
+ }
+
+ /**
+ * Retrieve the context document object.
+ * @return The context document object.
+ */
+ public Document getContextDocument()
+ {
+ if (contextDoc == null)
+ {
+ File contextFile = new File(baseDir, file);
+
+ try
+ {
+ contextDoc = builder.build(contextFile);
+ }
+ catch (Exception e)
+ {
+ throw new BuildException(e);
+ }
+ }
+ return contextDoc;
+ }
+ }
+
+}
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/AnakiaTask.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/AnakiaTask.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/java/org/apache/anakia/Escape.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/Escape.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/Escape.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/Escape.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,96 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * This class is for escaping CDATA sections. The code was
+ * "borrowed" from the JDOM code. Also included is escaping
+ * the " -> &quot; character and the conversion of newlines
+ * to the platform line separator.
+ *
+ * @author <a href="mailto:wglass@apache.org">Will Glass-Husain</a>
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @version $Id$
+ */
+public class Escape
+{
+ /**
+ *
+ */
+ public static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+ /**
+ * Empty constructor
+ */
+ public Escape()
+ {
+ // left blank on purpose
+ }
+
+ /**
+ * Do the escaping.
+ * @param st
+ * @return The escaped text.
+ */
+ public static final String getText(String st)
+ {
+ StringBuffer buff = new StringBuffer();
+ char[] block = st.toCharArray();
+ String stEntity = null;
+ int i, last;
+
+ for (i=0, last=0; i < block.length; i++)
+ {
+ switch(block[i])
+ {
+ case '<' :
+ stEntity = "<";
+ break;
+ case '>' :
+ stEntity = ">";
+ break;
+ case '&' :
+ stEntity = "&";
+ break;
+ case '"' :
+ stEntity = """;
+ break;
+ case '\n' :
+ stEntity = LINE_SEPARATOR;
+ break;
+ default :
+ /* no-op */
+ break;
+ }
+ if (stEntity != null)
+ {
+ buff.append(block, last, i - last);
+ buff.append(stEntity);
+ stEntity = null;
+ last = i + 1;
+ }
+ }
+ if(last < block.length)
+ {
+ buff.append(block, last, i - last);
+ }
+ return buff.toString();
+ }
+}
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/Escape.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/Escape.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/java/org/apache/anakia/NodeList.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/NodeList.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/NodeList.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/NodeList.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,509 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.jdom.Attribute;
+import org.jdom.CDATA;
+import org.jdom.Comment;
+import org.jdom.DocType;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.EntityRef;
+import org.jdom.ProcessingInstruction;
+import org.jdom.Text;
+import org.jdom.output.XMLOutputter;
+
+/**
+ * Provides a class for wrapping a list of JDOM objects primarily for use in template
+ * engines and other kinds of text transformation tools.
+ * It has a {@link #toString()} method that will output the XML serialized form of the
+ * nodes it contains - again focusing on template engine usage, as well as the
+ * {@link #selectNodes(String)} method that helps selecting a different set of nodes
+ * starting from the nodes in this list. The class also implements the {@link java.util.List}
+ * interface by simply delegating calls to the contained list (the {@link #subList(int, int)}
+ * method is implemented by delegating to the contained list and wrapping the returned
+ * sublist into a <code>NodeList</code>).
+ *
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @version $Id$
+ */
+public class NodeList implements List, Cloneable
+{
+ private static final AttributeXMLOutputter DEFAULT_OUTPUTTER =
+ new AttributeXMLOutputter();
+
+ /** The contained nodes */
+ private List nodes;
+
+ /**
+ * Creates an empty node list.
+ */
+ public NodeList()
+ {
+ nodes = new ArrayList();
+ }
+
+ /**
+ * Creates a node list that holds a single {@link Document} node.
+ * @param document
+ */
+ public NodeList(Document document)
+ {
+ this((Object)document);
+ }
+
+ /**
+ * Creates a node list that holds a single {@link Element} node.
+ * @param element
+ */
+ public NodeList(Element element)
+ {
+ this((Object)element);
+ }
+
+ private NodeList(Object object)
+ {
+ if(object == null)
+ {
+ throw new IllegalArgumentException(
+ "Cannot construct NodeList with null.");
+ }
+ nodes = new ArrayList(1);
+ nodes.add(object);
+ }
+
+ /**
+ * Creates a node list that holds a list of nodes.
+ * @param nodes the list of nodes this template should hold. The created
+ * template will copy the passed nodes list, so changes to the passed list
+ * will not affect the model.
+ */
+ public NodeList(List nodes)
+ {
+ this(nodes, true);
+ }
+
+ /**
+ * Creates a node list that holds a list of nodes.
+ * @param nodes the list of nodes this template should hold.
+ * @param copy if true, the created template will copy the passed nodes
+ * list, so changes to the passed list will not affect the model. If false,
+ * the model will reference the passed list and will sense changes in it,
+ * altough no operations on the list will be synchronized.
+ */
+ public NodeList(List nodes, boolean copy)
+ {
+ if(nodes == null)
+ {
+ throw new IllegalArgumentException(
+ "Cannot initialize NodeList with null list");
+ }
+ this.nodes = copy ? new ArrayList(nodes) : nodes;
+ }
+
+ /**
+ * Retrieves the underlying list used to store the nodes. Note however, that
+ * you can fully use the underlying list through the <code>List</code> interface
+ * of this class itself. You would probably access the underlying list only for
+ * synchronization purposes.
+ * @return The internal node List.
+ */
+ public List getList()
+ {
+ return nodes;
+ }
+
+ /**
+ * This method returns the string resulting from concatenation of string
+ * representations of its nodes. Each node is rendered using its XML
+ * serialization format. This greatly simplifies creating XML-transformation
+ * templates, as to output a node contained in variable x as XML fragment,
+ * you simply write ${x} in the template (or whatever your template engine
+ * uses as its expression syntax).
+ * @return The Nodelist as printable object.
+ */
+ public String toString()
+ {
+ if(nodes.isEmpty())
+ {
+ return "";
+ }
+
+ StringWriter sw = new StringWriter(nodes.size() * 128);
+ try
+ {
+ for(Iterator i = nodes.iterator(); i.hasNext();)
+ {
+ Object node = i.next();
+ if(node instanceof Element)
+ {
+ DEFAULT_OUTPUTTER.output((Element)node, sw);
+ }
+ else if(node instanceof Attribute)
+ {
+ DEFAULT_OUTPUTTER.output((Attribute)node, sw);
+ }
+ else if(node instanceof Text)
+ {
+ DEFAULT_OUTPUTTER.output((Text)node, sw);
+ }
+ else if(node instanceof Document)
+ {
+ DEFAULT_OUTPUTTER.output((Document)node, sw);
+ }
+ else if(node instanceof ProcessingInstruction)
+ {
+ DEFAULT_OUTPUTTER.output((ProcessingInstruction)node, sw);
+ }
+ else if(node instanceof Comment)
+ {
+ DEFAULT_OUTPUTTER.output((Comment)node, sw);
+ }
+ else if(node instanceof CDATA)
+ {
+ DEFAULT_OUTPUTTER.output((CDATA)node, sw);
+ }
+ else if(node instanceof DocType)
+ {
+ DEFAULT_OUTPUTTER.output((DocType)node, sw);
+ }
+ else if(node instanceof EntityRef)
+ {
+ DEFAULT_OUTPUTTER.output((EntityRef)node, sw);
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Cannot process a " +
+ (node == null
+ ? "null node"
+ : "node of class " + node.getClass().getName()));
+ }
+ }
+ }
+ catch(IOException e)
+ {
+ // Cannot happen as we work with a StringWriter in memory
+ throw new Error();
+ }
+ return sw.toString();
+ }
+
+ /**
+ * Returns a NodeList that contains the same nodes as this node list.
+ * @return A clone of this list.
+ * @throws CloneNotSupportedException if the contained list's class does
+ * not have an accessible no-arg constructor.
+ */
+ public Object clone()
+ throws CloneNotSupportedException
+ {
+ NodeList clonedList = (NodeList)super.clone();
+ clonedList.cloneNodes();
+ return clonedList;
+ }
+
+ private void cloneNodes()
+ throws CloneNotSupportedException
+ {
+ Class listClass = nodes.getClass();
+ try
+ {
+ List clonedNodes = (List)listClass.newInstance();
+ clonedNodes.addAll(nodes);
+ nodes = clonedNodes;
+ }
+ catch(IllegalAccessException e)
+ {
+ throw new CloneNotSupportedException("Cannot clone NodeList since"
+ + " there is no accessible no-arg constructor on class "
+ + listClass.getName());
+ }
+ catch(InstantiationException e)
+ {
+ // Cannot happen as listClass represents a concrete, non-primitive,
+ // non-array, non-void class - there's an instance of it in "nodes"
+ // which proves these assumptions.
+ throw new Error();
+ }
+ }
+
+ /**
+ * Returns the hash code of the contained list.
+ * @return The hashcode of the list.
+ */
+ public int hashCode()
+ {
+ return nodes.hashCode();
+ }
+
+ /**
+ * Tests for equality with another object.
+ * @param o the object to test for equality
+ * @return true if the other object is also a NodeList and their contained
+ * {@link List} objects evaluate as equals.
+ */
+ public boolean equals(Object o)
+ {
+ return o instanceof NodeList
+ ? ((NodeList)o).nodes.equals(nodes)
+ : false;
+ }
+
+ /**
+ * Applies an XPath expression to the node list and returns the resulting
+ * node list. In order for this method to work, your application must have
+ * access to <a href="http://code.werken.com">werken.xpath</a> library
+ * classes. The implementation does cache the parsed format of XPath
+ * expressions in a weak hash map, keyed by the string representation of
+ * the XPath expression. As the string object passed as the argument is
+ * usually kept in the parsed template, this ensures that each XPath
+ * expression is parsed only once during the lifetime of the template that
+ * first invoked it.
+ * @param xpathString the XPath expression you wish to apply
+ * @return a NodeList representing the nodes that are the result of
+ * application of the XPath to the current node list. It can be empty.
+ */
+ public NodeList selectNodes(String xpathString)
+ {
+ return new NodeList(XPathCache.getXPath(xpathString).applyTo(nodes), false);
+ }
+
+// List methods implemented hereafter
+
+ /**
+ * @see java.util.List#add(java.lang.Object)
+ */
+ public boolean add(Object o)
+ {
+ return nodes.add(o);
+ }
+
+ /**
+ * @see java.util.List#add(int, java.lang.Object)
+ */
+ public void add(int index, Object o)
+ {
+ nodes.add(index, o);
+ }
+
+ /**
+ * @see java.util.List#addAll(java.util.Collection)
+ */
+ public boolean addAll(Collection c)
+ {
+ return nodes.addAll(c);
+ }
+
+ /**
+ * @see java.util.List#addAll(int, java.util.Collection)
+ */
+ public boolean addAll(int index, Collection c)
+ {
+ return nodes.addAll(index, c);
+ }
+
+ /**
+ * @see java.util.List#clear()
+ */
+ public void clear()
+ {
+ nodes.clear();
+ }
+
+ /**
+ * @see java.util.List#contains(java.lang.Object)
+ */
+ public boolean contains(Object o)
+ {
+ return nodes.contains(o);
+ }
+
+ /**
+ * @see java.util.List#containsAll(java.util.Collection)
+ */
+ public boolean containsAll(Collection c)
+ {
+ return nodes.containsAll(c);
+ }
+
+ /**
+ * @see java.util.List#get(int)
+ */
+ public Object get(int index)
+ {
+ return nodes.get(index);
+ }
+
+ /**
+ * @see java.util.List#indexOf(java.lang.Object)
+ */
+ public int indexOf(Object o)
+ {
+ return nodes.indexOf(o);
+ }
+
+ /**
+ * @see java.util.List#isEmpty()
+ */
+ public boolean isEmpty()
+ {
+ return nodes.isEmpty();
+ }
+
+ /**
+ * @see java.util.List#iterator()
+ */
+ public Iterator iterator()
+ {
+ return nodes.iterator();
+ }
+
+ /**
+ * @see java.util.List#lastIndexOf(java.lang.Object)
+ */
+ public int lastIndexOf(Object o)
+ {
+ return nodes.lastIndexOf(o);
+ }
+
+ /**
+ * @see java.util.List#listIterator()
+ */
+ public ListIterator listIterator()
+ {
+ return nodes.listIterator();
+ }
+
+ /**
+ * @see java.util.List#listIterator(int)
+ */
+ public ListIterator listIterator(int index)
+ {
+ return nodes.listIterator(index);
+ }
+
+ /**
+ * @see java.util.List#remove(int)
+ */
+ public Object remove(int index)
+ {
+ return nodes.remove(index);
+ }
+
+ /**
+ * @see java.util.List#remove(java.lang.Object)
+ */
+ public boolean remove(Object o)
+ {
+ return nodes.remove(o);
+ }
+
+ /**
+ * @see java.util.List#removeAll(java.util.Collection)
+ */
+ public boolean removeAll(Collection c)
+ {
+ return nodes.removeAll(c);
+ }
+
+ /**
+ * @see java.util.List#retainAll(java.util.Collection)
+ */
+ public boolean retainAll(Collection c)
+ {
+ return nodes.retainAll(c);
+ }
+
+ /**
+ * @see java.util.List#set(int, java.lang.Object)
+ */
+ public Object set(int index, Object o)
+ {
+ return nodes.set(index, o);
+ }
+
+ /**
+ * @see java.util.List#size()
+ */
+ public int size()
+ {
+ return nodes.size();
+ }
+
+ /**
+ * @see java.util.List#subList(int, int)
+ */
+ public List subList(int fromIndex, int toIndex)
+ {
+ return new NodeList(nodes.subList(fromIndex, toIndex));
+ }
+
+ /**
+ * @see java.util.List#toArray()
+ */
+ public Object[] toArray()
+ {
+ return nodes.toArray();
+ }
+
+ /**
+ * @see java.util.List#toArray(java.lang.Object[])
+ */
+ public Object[] toArray(Object[] a)
+ {
+ return nodes.toArray(a);
+ }
+
+ /**
+ * A special subclass of XMLOutputter that will be used to output
+ * Attribute nodes. As a subclass of XMLOutputter it can use its protected
+ * method escapeAttributeEntities() to serialize the attribute
+ * appropriately.
+ */
+ private static final class AttributeXMLOutputter extends XMLOutputter
+ {
+ /**
+ * @param attribute
+ * @param out
+ * @throws IOException
+ */
+ public void output(Attribute attribute, Writer out)
+ throws IOException
+ {
+ out.write(" ");
+ out.write(attribute.getQualifiedName());
+ out.write("=");
+
+ out.write("\"");
+ out.write(escapeAttributeEntities(attribute.getValue()));
+ out.write("\"");
+ }
+ }
+}
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/NodeList.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/NodeList.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/java/org/apache/anakia/OutputWrapper.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/OutputWrapper.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/OutputWrapper.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/OutputWrapper.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,82 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import org.jdom.Element;
+import org.jdom.output.XMLOutputter;
+import org.jdom.output.Format;
+
+/**
+ * This class extends XMLOutputter in order to provide
+ * a way to walk an Element tree into a String.
+ *
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
+ * @version $Id$
+ */
+public class OutputWrapper extends XMLOutputter
+{
+ /**
+ * Empty constructor
+ */
+ public OutputWrapper()
+ {
+ }
+
+ /**
+ * @param f
+ */
+ public OutputWrapper(Format f)
+ {
+ super(f);
+ }
+
+ /**
+ * This method walks an Element tree into a String. The cool
+ * thing about it is that it will strip off the first Element.
+ * For example, if you have:
+ * <p>
+ * <td> foo <strong>bar</strong> ack </td>
+ * </p>
+ * It will output
+ * <p>
+ * foo <strong>bar</strong> ack </td>
+ * </p>
+ * @param element
+ * @param strip
+ * @return The output string.
+ */
+ public String outputString(Element element, boolean strip)
+ {
+ StringWriter buff = new StringWriter();
+
+ try
+ {
+ outputElementContent(element, buff);
+ }
+ catch (IOException e)
+ {
+ }
+ return buff.toString();
+ }
+}
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/OutputWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/OutputWrapper.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/java/org/apache/anakia/TreeWalker.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/TreeWalker.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/TreeWalker.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/TreeWalker.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,77 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.jdom.Element;
+
+/**
+ * This class allows you to walk a tree of JDOM Element objects.
+ * It first walks the tree itself starting at the Element passed
+ * into allElements() and stores each node of the tree
+ * in a Vector which allElements() returns as a result of its
+ * execution. You can then use a #foreach in Velocity to walk
+ * over the Vector and visit each Element node. However, you can
+ * achieve the same effect by calling <code>element.selectNodes("//*")</code>.
+ *
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @version $Id$
+ */
+public class TreeWalker
+{
+ /**
+ * Empty constructor
+ */
+ public TreeWalker()
+ {
+ // Left blank
+ }
+
+ /**
+ * Creates a new Vector and walks the Element tree.
+ *
+ * @param e the starting Element node
+ * @return Vector a vector of Element nodes
+ */
+ public NodeList allElements(Element e)
+ {
+ ArrayList theElements = new ArrayList();
+ treeWalk (e, theElements);
+ return new NodeList(theElements, false);
+ }
+
+ /**
+ * A recursive method to walk the Element tree.
+ * @param Element the current Element
+ */
+ private final void treeWalk(Element e, Collection theElements )
+ {
+ for (Iterator i=e.getChildren().iterator(); i.hasNext(); )
+ {
+ Element child = (Element)i.next();
+ theElements.add(child);
+ treeWalk(child, theElements);
+ }
+ }
+}
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/TreeWalker.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/TreeWalker.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/java/org/apache/anakia/XPathCache.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/XPathCache.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/XPathCache.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/XPathCache.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,64 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import com.werken.xpath.XPath;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * Provides a cache for XPath expressions. Used by {@link NodeList} and
+ * {@link AnakiaElement} to minimize XPath parsing in their
+ * <code>selectNodes()</code> methods.
+ *
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @version $Id$
+ */
+class XPathCache
+{
+ // Cache of already parsed XPath expressions, keyed by String representations
+ // of the expression as passed to getXPath().
+ private static final Map XPATH_CACHE = new WeakHashMap();
+
+ private XPathCache()
+ {
+ }
+
+ /**
+ * Returns an XPath object representing the requested XPath expression.
+ * A cached object is returned if it already exists for the requested expression.
+ * @param xpathString the XPath expression to parse
+ * @return the XPath object that represents the parsed XPath expression.
+ */
+ static XPath getXPath(String xpathString)
+ {
+ XPath xpath = null;
+ synchronized(XPATH_CACHE)
+ {
+ xpath = (XPath)XPATH_CACHE.get(xpathString);
+ if(xpath == null)
+ {
+ xpath = new XPath(xpathString);
+ XPATH_CACHE.put(xpathString, xpath);
+ }
+ }
+ return xpath;
+ }
+}
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/XPathCache.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/XPathCache.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/java/org/apache/anakia/XPathTool.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/java/org/apache/anakia/XPathTool.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/java/org/apache/anakia/XPathTool.java (added)
+++ velocity/anakia/trunk/src/java/org/apache/anakia/XPathTool.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,131 @@
+package org.apache.anakia;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.List;
+
+import org.jdom.Document;
+import org.jdom.Element;
+
+/**
+ * This class adds an entrypoint into XPath functionality,
+ * for Anakia.
+ * <p>
+ * All methods take a string XPath specification, along with
+ * a context, and produces a resulting java.util.List.
+ * <p>
+ * The W3C XPath Specification (http://www.w3.org/TR/xpath) refers
+ * to NodeSets repeatedly, but this implementation simply uses
+ * java.util.List to hold all Nodes. A 'Node' is any object in
+ * a JDOM object tree, such as an org.jdom.Element, org.jdom.Document,
+ * or org.jdom.Attribute.
+ * <p>
+ * To use it in Velocity, do this:
+ * <p>
+ * <pre>
+ * #set $authors = $xpath.applyTo("document/author", $root)
+ * #foreach ($author in $authors)
+ * $author.getValue()
+ * #end
+ * #set $chapterTitles = $xpath.applyTo("document/chapter/@title", $root)
+ * #foreach ($title in $chapterTitles)
+ * $title.getValue()
+ * #end
+ * </pre>
+ * <p>
+ * In newer Anakia builds, this class is obsoleted in favor of calling
+ * <code>selectNodes()</code> on the element directly:
+ * <pre>
+ * #set $authors = $root.selectNodes("document/author")
+ * #foreach ($author in $authors)
+ * $author.getValue()
+ * #end
+ * #set $chapterTitles = $root.selectNodes("document/chapter/@title")
+ * #foreach ($title in $chapterTitles)
+ * $title.getValue()
+ * #end
+ * </pre>
+ * <p>
+ *
+ * @author <a href="mailto:bob@werken.com">bob mcwhirter</a>
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
+ * @version $Id$
+ */
+public class XPathTool
+{
+ /**
+ * Constructor does nothing, as this is mostly
+ * just objectified static methods
+ */
+ public XPathTool()
+ {
+ // RuntimeSingleton.info("XPathTool::XPathTool()");
+ // intentionally left blank
+ }
+
+ /**
+ * Apply an XPath to a JDOM Document
+ *
+ * @param xpathSpec The XPath to apply
+ * @param doc The Document context
+ *
+ * @return A list of selected nodes
+ */
+ public NodeList applyTo(String xpathSpec,
+ Document doc)
+ {
+ //RuntimeSingleton.info("XPathTool::applyTo(String, Document)");
+ return new NodeList(XPathCache.getXPath(xpathSpec).applyTo( doc ), false);
+ }
+
+ /**
+ * Apply an XPath to a JDOM Element
+ *
+ * @param xpathSpec The XPath to apply
+ * @param elem The Element context
+ *
+ * @return A list of selected nodes
+ */
+ public NodeList applyTo(String xpathSpec,
+ Element elem)
+ {
+ //RuntimeSingleton.info("XPathTool::applyTo(String, Element)");
+ return new NodeList(XPathCache.getXPath(xpathSpec).applyTo( elem ), false);
+ }
+
+ /**
+ * Apply an XPath to a nodeset
+ *
+ * @param xpathSpec The XPath to apply
+ * @param nodeSet The nodeset context
+ *
+ * @return A list of selected nodes
+ */
+ public NodeList applyTo(String xpathSpec,
+ List nodeSet)
+ {
+ //RuntimeSingleton.info("XPathTool::applyTo(String, List)");
+ return new NodeList(XPathCache.getXPath(xpathSpec).applyTo( nodeSet ), false);
+ }
+}
+
+
+
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/XPathTool.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/java/org/apache/anakia/XPathTool.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/test/org/apache/anakia/AnakiaTestCase.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/test/org/apache/anakia/AnakiaTestCase.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/test/org/apache/anakia/AnakiaTestCase.java (added)
+++ velocity/anakia/trunk/src/test/org/apache/anakia/AnakiaTestCase.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,118 @@
+package org.apache.anakia;
+
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.apache.anakia.test.Log;
+import org.apache.anakia.test.TestUtil;
+
+
+/**
+ * This is a test case for Anakia. Right now, it simply will compare
+ * two index.html files together. These are produced as a result of
+ * first running Anakia and then running this test.
+ *
+ * @version $Id$
+ */
+public class AnakiaTestCase extends TestCase
+{
+ public static final String TEST_DIR_KEY = "test.compare.dir";
+ public static final String RESULTS_DIR_KEY = "test.results.dir";
+
+ private String resultsDir;
+ private String compareDir;
+
+ /**
+ * Creates a new instance.
+ *
+ */
+ public AnakiaTestCase(String name)
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(AnakiaTestCase.class);
+ }
+
+ /**
+ * Find the directories.
+ */
+ public void setUp()
+ {
+ resultsDir = System.getProperty(RESULTS_DIR_KEY, "bin/test") + "/anakia";
+ compareDir = System.getProperty(TEST_DIR_KEY, "test") + "/anakia/compare";
+ }
+
+ /**
+ * Runs the test. This is empty on purpose because the
+ * code to do the Anakia output is in the .xml file that runs
+ * this test.
+ */
+ public void testAnakiaResults ()
+ throws Exception
+ {
+ TestUtil.assureResultsDirectoryExists(resultsDir);
+
+ // compare with custom context
+ if (!TestUtil.compareFiles(
+ new File(compareDir, "index.html").toString(),
+ new File(resultsDir, "index.html").toString()))
+ {
+ fail("Anakia results are incorrect");
+ }
+ else
+ {
+ Log.log ("Passed (standard)!");
+ }
+ }
+
+ /**
+ * Runs the test. This is empty on purpose because the
+ * code to do the Anakia output is in the .xml file that runs
+ * this test.
+ */
+ public void testAnakiaCustomContextResults ()
+ throws Exception
+ {
+ TestUtil.assureResultsDirectoryExists(resultsDir);
+
+ // compare with custom context
+ if (!TestUtil.compareFiles(
+ new File(compareDir, "index.context.html").toString(),
+ new File(resultsDir, "index.context.html").toString()))
+ {
+ fail("Anakia results are incorrect");
+ }
+ else
+ {
+ Log.log ("Passed (custom context)!");
+ }
+ }
+
+
+}
Propchange: velocity/anakia/trunk/src/test/org/apache/anakia/AnakiaTestCase.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/test/org/apache/anakia/AnakiaTestCase.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/test/org/apache/anakia/test/Log.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/test/org/apache/anakia/test/Log.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/test/org/apache/anakia/test/Log.java (added)
+++ velocity/anakia/trunk/src/test/org/apache/anakia/test/Log.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,46 @@
+package org.apache.anakia.test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+* Simple class to log messages when running tests
+*
+* @version $Id$
+*/
+
+public class Log
+{
+
+ /**
+ * Do not instantiate.
+ */
+ private Log ()
+ {
+ }
+
+ /**
+ * Output a message;
+ * @param message
+ */
+ public static void log(String message)
+ {
+ System.out.println(message);
+ }
+}
Propchange: velocity/anakia/trunk/src/test/org/apache/anakia/test/Log.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/test/org/apache/anakia/test/Log.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/src/test/org/apache/anakia/test/TestUtil.java
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/src/test/org/apache/anakia/test/TestUtil.java?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/src/test/org/apache/anakia/test/TestUtil.java (added)
+++ velocity/anakia/trunk/src/test/org/apache/anakia/test/TestUtil.java Sat Mar 31 13:51:49 2007
@@ -0,0 +1,119 @@
+package org.apache.anakia.test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+
+
+/**
+ * Miscellaneous routines to help with testing
+ *
+ * @version $Id$
+ */
+public class TestUtil
+{
+
+ /**
+ * Do not instantiate.
+ */
+ private TestUtil()
+ {
+ }
+
+ /**
+ * Assures that the results directory exists. If the results directory
+ * cannot be created, fails the test.
+ */
+ public static void assureResultsDirectoryExists (String resultsDirectory)
+ {
+ File dir = new File(resultsDirectory);
+ if (!dir.exists())
+ {
+ Log.log("Template results directory does not exist");
+ if (dir.mkdirs())
+ {
+ Log.log("Created template results directory");
+ }
+ else
+ {
+ String errMsg = "Unable to create template results directory";
+ Log.log(errMsg);
+ throw new RuntimeException(errMsg);
+ }
+ }
+ }
+
+ /**
+ * Normalizes lines to account for platform differences. Macs use
+ * a single \r, DOS derived operating systems use \r\n, and Unix
+ * uses \n. Replace each with a single \n.
+ *
+ * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
+ * @return source with all line terminations changed to Unix style
+ */
+ public static String normalizeNewlines (String source)
+ {
+ return source.replaceAll("\r[\r]?[\n]","\n");
+ }
+
+ /**
+ * Returns whether the processed template matches the
+ * content of the provided comparison file.
+ *
+ * @return Whether the output matches the contents
+ * of the comparison file.
+ *
+ * @exception Exception Test failure condition.
+ */
+ public static boolean compareFiles(String compareFileName, String resultsFileName)
+ throws Exception
+ {
+ Log.log("Comparing result file '" + resultsFileName + "' with compare file '" + compareFileName + "'");
+ String resultText = org.apache.velocity.util.StringUtils.fileContentsToString(resultsFileName);
+
+ return compareTextWithFile(resultText, compareFileName);
+ }
+
+
+ /**
+ * Returns whether the processed template matches the
+ * content of the provided comparison file.
+ *
+ * @return Whether the output matches the contents
+ * of the comparison file.
+ *
+ * @exception Exception Test failure condition.
+ */
+ public static boolean compareTextWithFile(String resultText, String compareFileName)
+ throws Exception
+ {
+ String compareText = org.apache.velocity.util.StringUtils.fileContentsToString(compareFileName);
+
+ /*
+ * normalize each wrt newline
+ */
+
+ String normalizedResultText = normalizeNewlines(resultText);
+ String normalizedCompareText = normalizeNewlines(compareText);
+ return normalizedResultText.equals( normalizedCompareText );
+ }
+
+
+}
Propchange: velocity/anakia/trunk/src/test/org/apache/anakia/test/TestUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/src/test/org/apache/anakia/test/TestUtil.java
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/compare/index.context.html
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/compare/index.context.html?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/compare/index.context.html (added)
+++ velocity/anakia/trunk/test/anakia/compare/index.context.html Sat Mar 31 13:51:49 2007
@@ -0,0 +1,65 @@
+<!-- Content Stylesheet for Site -->
+
+
+<!-- start the processing -->
+ <!-- ====================================================================== -->
+ <!-- Main Page Section -->
+ <!-- ====================================================================== -->
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+ <meta name="author" value="$au.getText()">
+ <meta name="email" value="$em.getValue()">
+ <title>The Jakarta Project</title>
+ </head>
+
+ <body bgcolor="#ffffff" text="#000000" link="#525D76">
+ <table border="1">
+ <tr>
+ <td>
+ <strong>Home</strong>
+ <ul>
+ <li> <a href="./index.html">Front Page</a>
+</li>
+ </ul>
+ <strong>About</strong>
+ <ul>
+ <li> <a href="./about/index.html">About</a>
+</li>
+ </ul>
+
+ <strong>Other Context</strong>
+ <ul>
+ <li> <a href="./index.html">Front Page OC</a>
+</li>
+ </ul>
+ <strong>Other About</strong>
+ <ul>
+ <li> <a href="./about/index.html">About OC</a>
+</li>
+ </ul>
+ </td>
+ <td>
+ <p> This is an example template that gets processed. </p>
+ <img src="./images/velocity.gif" width="329" height="105" align="">
+ <table border="1">
+ <tr>
+ <td> It even has a table in it! </td>
+ </tr>
+ </table>
+ <h3>And an h3 tag</h3>
+ <p> here is another section </p>
+ <p>
+ <a href="./about/index.html">A link to a sub page</a>
+ </p>
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+<!-- end the processing -->
+
+
+
+
+
Propchange: velocity/anakia/trunk/test/anakia/compare/index.context.html
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/test/anakia/compare/index.context.html
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/compare/index.html
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/compare/index.html?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/compare/index.html (added)
+++ velocity/anakia/trunk/test/anakia/compare/index.html Sat Mar 31 13:51:49 2007
@@ -0,0 +1,55 @@
+<!-- Content Stylesheet for Site -->
+
+
+<!-- start the processing -->
+ <!-- ====================================================================== -->
+ <!-- Main Page Section -->
+ <!-- ====================================================================== -->
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+ <meta name="author" value="$au.getText()">
+ <meta name="email" value="$em.getValue()">
+ <title>The Jakarta Project</title>
+ </head>
+
+ <body bgcolor="#ffffff" text="#000000" link="#525D76">
+ <table border="1">
+ <tr>
+ <td>
+ <strong>Home</strong>
+ <ul>
+ <li> <a href="./index.html">Front Page</a>
+</li>
+ </ul>
+ <strong>About</strong>
+ <ul>
+ <li> <a href="./about/index.html">About</a>
+</li>
+ </ul>
+
+ </td>
+ <td>
+ <p> This is an example template that gets processed. </p>
+ <img src="./images/velocity.gif" width="329" height="105" align="">
+ <table border="1">
+ <tr>
+ <td> It even has a table in it! </td>
+ </tr>
+ </table>
+ <h3>And an h3 tag</h3>
+ <p> here is another section </p>
+ <p>
+ <a href="./about/index.html">A link to a sub page</a>
+ </p>
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+<!-- end the processing -->
+
+
+
+
+
Propchange: velocity/anakia/trunk/test/anakia/compare/index.html
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/test/anakia/compare/index.html
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/compare/index.html.bak
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/compare/index.html.bak?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/compare/index.html.bak (added)
+++ velocity/anakia/trunk/test/anakia/compare/index.html.bak Sat Mar 31 13:51:49 2007
@@ -0,0 +1,55 @@
+<!-- Content Stylesheet for Site -->
+
+
+<!-- start the processing -->
+ <!-- ====================================================================== -->
+ <!-- Main Page Section -->
+ <!-- ====================================================================== -->
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+ <meta name="author" value="$au.getText()">
+ <meta name="email" value="$em.getValue()">
+ <title>The Jakarta Project</title>
+ </head>
+
+ <body bgcolor="#ffffff" text="#000000" link="#525D76">
+ <table border="1">
+ <tr>
+ <td>
+ <strong>Home</strong>
+ <ul>
+ <li> <a href="./index.html">Front Page</a>
+</li>
+ </ul>
+ <strong>About</strong>
+ <ul>
+ <li> <a href="./about/index.html">About</a>
+</li>
+ </ul>
+
+ </td>
+ <td>
+ <p> This is an example template that gets processed. </p>
+ <img src="./images/velocity.gif" width="329" height="105" align="">
+ <table border="1">
+ <tr>
+ <td> It even has a table in it! </td>
+ </tr>
+ </table>
+ <h3>And an h3 tag</h3>
+ <p> here is another section </p>
+ <p>
+ <a href="./about/index.html">A link to a sub page</a>
+ </p>
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+<!-- end the processing -->
+
+
+
+
+
Added: velocity/anakia/trunk/test/anakia/velocity.properties
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/velocity.properties?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/velocity.properties (added)
+++ velocity/anakia/trunk/test/anakia/velocity.properties Sat Mar 31 13:51:49 2007
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
Propchange: velocity/anakia/trunk/test/anakia/velocity.properties
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/test/anakia/velocity.properties
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/xdocs/index.xml
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/xdocs/index.xml?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/xdocs/index.xml (added)
+++ velocity/anakia/trunk/test/anakia/xdocs/index.xml Sat Mar 31 13:51:49 2007
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document>
+ <properties>
+ <author email="jon@latchkey.com">Jon S. Stevens</author>
+ <title>The Jakarta Project</title>
+ </properties>
+ <body>
+ <section name="Section 1">
+ <p> This is an example template that gets processed. </p>
+ <img src="/images/velocity.gif" width="329" height="105"/>
+ <table border="1">
+ <tr>
+ <td> It even has a table in it! </td>
+ </tr>
+ </table>
+ <h3>And an h3 tag</h3>
+ </section>
+ <section name="Section 2">
+ <p> here is another section </p>
+ </section>
+ <section name="section 3">
+ <p>
+ <a href="./about/index.html">A link to a sub page</a>
+ </p>
+ </section>
+ </body>
+</document>
Propchange: velocity/anakia/trunk/test/anakia/xdocs/index.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/test/anakia/xdocs/index.xml
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/customContext.xml
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/xdocs/stylesheets/customContext.xml?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/xdocs/stylesheets/customContext.xml (added)
+++ velocity/anakia/trunk/test/anakia/xdocs/stylesheets/customContext.xml Sat Mar 31 13:51:49 2007
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project name="Jakarta Site" href="http://jakarta.apache.org/">
+ <body>
+ <menu name="Other Context">
+ <item name="Front Page OC" href="/index.html"/>
+ </menu>
+ <menu name="Other About">
+ <item name="About OC" href="/about/index.html"/>
+ </menu>
+ </body>
+</project>
Propchange: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/customContext.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/customContext.xml
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/project.xml
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/xdocs/stylesheets/project.xml?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/xdocs/stylesheets/project.xml (added)
+++ velocity/anakia/trunk/test/anakia/xdocs/stylesheets/project.xml Sat Mar 31 13:51:49 2007
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project name="Jakarta Site"
+ href="http://jakarta.apache.org/">
+
+ <title>Jakarta Site</title>
+
+ <body>
+ <menu name="Home">
+ <item name="Front Page" href="/index.html"/>
+ </menu>
+
+ <menu name="About">
+ <item name="About" href="/about/index.html"/>
+ </menu>
+ </body>
+</project>
Propchange: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/project.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/project.xml
------------------------------------------------------------------------------
svn:keywords = Id Author Date Revision
Added: velocity/anakia/trunk/test/anakia/xdocs/stylesheets/site.vsl
URL: http://svn.apache.org/viewvc/velocity/anakia/trunk/test/anakia/xdocs/stylesheets/site.vsl?view=auto&rev=524478
==============================================================================
--- velocity/anakia/trunk/test/anakia/xdocs/stylesheets/site.vsl (added)
+++ velocity/anakia/trunk/test/anakia/xdocs/stylesheets/site.vsl Sat Mar 31 13:51:49 2007
@@ -0,0 +1,108 @@
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements. See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership. The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied. See the License for the
+## specific language governing permissions and limitations
+## under the License.
+<!-- Content Stylesheet for Site -->
+
+ ## Defined variables
+ #set ($bodybg = "#ffffff")
+ #set ($bodyfg = "#000000")
+ #set ($bodylink = "#525D76")
+ #set ($bannerbg = "#525D76")
+ #set ($bannerfg = "#ffffff")
+ #set ($tablethbg = "#039acc")
+ #set ($tabletdbg = "#a0ddf0")
+
+<!-- start the processing -->
+#document()
+<!-- end the processing -->
+
+## This is where the macro's live
+
+#macro ( makeProject )
+ #set ($menus = $xpath.applyTo("body/menu", $project))
+
+ #foreach ( $menu in $menus )
+ <strong>$menu.getAttributeValue("name")</strong>
+ <ul>
+ #foreach ( $item in $menu.getChildren() )
+ #set ($name = $item.getAttributeValue("name"))
+ <li>#projectanchor($name $item.getAttributeValue("href"))</li>
+ #end
+ </ul>
+ #end
+#end
+
+#macro ( image $value )
+#if ($value.getAttributeValue("width"))
+#set ($width=$value.getAttributeValue("width"))
+#end
+#if ($value.getAttributeValue("height"))
+#set ($height=$value.getAttributeValue("height"))
+#end
+#if ($value.getAttributeValue("align"))
+#set ($align=$value.getAttributeValue("align"))
+#end
+<img src="$relativePath$value.getAttributeValue("src")" width="$!width" height="$!height" align="$!align">
+#end
+
+#macro ( projectanchor $name $value )
+ <a href="$relativePath$value">$name</a>
+#end
+#macro ( metaauthor $author $email )
+ <meta name="author" value="$author">
+ <meta name="email" value="$email">
+#end
+
+#macro (document)
+ <!-- ====================================================================== -->
+ <!-- Main Page Section -->
+ <!-- ====================================================================== -->
+ <html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
+
+ ## set ($au = $root.getChild("properties").getChild("author").getText())
+ ## set ($em = $root.getChild("properties").getChild("author").getAttributeValue("email"))
+ #metaauthor ( $au.getText() $em.getValue() )
+
+ <title>$root.getChild("properties").getChild("title").getText()</title>
+ </head>
+
+ <body bgcolor="$bodybg" text="$bodyfg" link="$bodylink">
+ <table border="1">
+ <tr>
+ <td>
+ #makeProject()
+ </td>
+ <td>
+ ## set ($allSections = $root.getChild("body").getChildren("section"))
+ #set ($allSections = $xpath.applyTo("body/section", $root))
+
+ #foreach ( $section in $allSections )
+ #foreach ( $item in $section.getChildren() )
+ #if ($item.getName().equals("img"))
+ #image ($item)
+ #else
+ $xmlout.outputString($item)
+ #end
+ #end
+ #end
+ </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+#end