jon         01/08/07 21:30:47

  Modified:    src/java/org/apache/velocity/anakia AnakiaTask.java
                        TreeWalker.java XPathTool.java
  Added:       src/java/org/apache/velocity/anakia AnakiaElement.java
                        AnakiaJDOMFactory.java NodeList.java
                        XPathCache.java
  Log:
  integrate in Attila Szegedi's patches to improve the XPath support within
  Anakia
  
  Revision  Changes    Path
  1.31      +31 -17    
jakarta-velocity/src/java/org/apache/velocity/anakia/AnakiaTask.java
  
  Index: AnakiaTask.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/anakia/AnakiaTask.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- AnakiaTask.java   2001/08/07 22:30:15     1.30
  +++ AnakiaTask.java   2001/08/08 04:30:47     1.31
  @@ -93,7 +93,8 @@
    * <a href="http://jakarta.apache.org/velocity/anakia.html";>Website</a>.
    *   
    * @author <a href="mailto:[EMAIL PROTECTED]";>Jon S. Stevens</a>
  - * @version $Id: AnakiaTask.java,v 1.30 2001/08/07 22:30:15 geirm Exp $
  + * @author <a href="mailto:[EMAIL PROTECTED]";>Attila Szegedi</a>
  + * @version $Id: AnakiaTask.java,v 1.31 2001/08/08 04:30:47 jon Exp $
    */
   public class AnakiaTask extends MatchingTask
   {
  @@ -140,6 +141,7 @@
       /** the file to get the velocity properties file */
       private File velocityPropertiesFile = null;
   
  +    /** the VelocityEngine instance to use */
       private VelocityEngine ve = new VelocityEngine();
   
       /**
  @@ -148,6 +150,7 @@
       public AnakiaTask()
       {
           builder = new SAXBuilder(DEFAULT_SAX_DRIVER_CLASS);
  +        builder.setFactory(new AnakiaJDOMFactory());
       }
   
       /**
  @@ -214,7 +217,6 @@
            }
        }
   
  -
       /**
        * Allow people to set the path to the velocity.properties file
        * This file is found relative to the path where the JVM was run.
  @@ -285,7 +287,9 @@
           {
               projectFile = new File(baseDir, projectAttribute);
               if (projectFile.exists())
  +            {
                   projectFileLastModified = projectFile.lastModified();
  +            }
               else
               {
                   log ("Project file is defined, but could not be located: " + 
  @@ -293,7 +297,8 @@
                   projectFile = null;
               }
           }
  -        
  +
  +        Document projectDocument = null;
           try
           {
               if ( velocityPropertiesFile.exists() )
  @@ -304,13 +309,17 @@
               {
                   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)
           {
  @@ -325,14 +334,15 @@
           list = scanner.getIncludedFiles();
           for (int i = 0;i < list.length; ++i)
           {
  -            process( baseDir, list[i], destDir );
  +            process( baseDir, list[i], destDir, projectDocument );
           }
       }    
       
       /**
        * Process an XML file using Velocity
        */
  -    private void process(File baseDir, String xmlFile, File destDir)
  +    private void process(File baseDir, String xmlFile, File destDir, 
  +                         Document projectDocument)
           throws BuildException
       {
           File   outFile=null;
  @@ -360,13 +370,7 @@
   
                   // Build the JDOM Document
                   Document root = builder.build(inFile);
  -                // Build the Project file document
  -                // FIXME: this should happen in the execute method since
  -                // it really only needs to be done once
  -                Document projectDocument = null;
  -                if (projectFile != null)
  -                    projectDocument = builder.build(projectFile);
  -    
  +
                   // Shove things into the Context
                   VelocityContext context = new VelocityContext();
   
  @@ -394,8 +398,10 @@
   
                   // only put this into the context if it exists.
                   if (projectDocument != null)
  +                {
                       context.put ("project", projectDocument.getRootElement());
  -
  +                }
  +                
                   // Process the VSL template with the context and write out
                   // the result as the outFile.
                   writer = new BufferedWriter(new OutputStreamWriter(
  @@ -439,7 +445,10 @@
           catch (Throwable e)
           {
   //            log("Failed to process " + inFile, Project.MSG_INFO);
  -            if (outFile != null ) outFile.delete();
  +            if (outFile != null)
  +            {
  +                outFile.delete();
  +            }
               e.printStackTrace();
           }        
           finally
  @@ -475,10 +484,15 @@
           {
               sb.append ("../");
           }
  +
           if (sb.toString().length() > 0)
  +        {
               return StringUtils.chop(sb.toString(), 1);
  +        }
           else
  -            return ".";    
  +        {
  +            return ".";
  +        }
       }
       
       /**
  
  
  
  1.5       +12 -12    
jakarta-velocity/src/java/org/apache/velocity/anakia/TreeWalker.java
  
  Index: TreeWalker.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/anakia/TreeWalker.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- TreeWalker.java   2001/03/20 00:47:44     1.4
  +++ TreeWalker.java   2001/08/08 04:30:47     1.5
  @@ -54,8 +54,9 @@
    * <http://www.apache.org/>.
    */
   
  +import java.util.ArrayList;
  +import java.util.Collection;
   import java.util.Iterator;
  -import java.util.Vector;
   
   import org.jdom.Document;
   import org.jdom.Element;
  @@ -67,16 +68,15 @@
    * 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.
  + * 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:[EMAIL PROTECTED]";>Jon S. Stevens</a>
  - * @version $Id: TreeWalker.java,v 1.4 2001/03/20 00:47:44 jon Exp $
  + * @author <a href="mailto:[EMAIL PROTECTED]";>Attila Szegedi</a>
  + * @version $Id: TreeWalker.java,v 1.5 2001/08/08 04:30:47 jon Exp $
    */
   public class TreeWalker
   {
  -    /** the cache of Element objects */
  -    private Vector theElements = null;
  -    
       /**
        * Empty constructor
        */
  @@ -91,24 +91,24 @@
        * @param Element the starting Element node
        * @return Vector a vector of Element nodes
        */
  -    public Vector allElements(Element e)
  +    public NodeList allElements(Element e)
       {
  -        theElements = new Vector();
  -        treeWalk (e);
  -        return this.theElements;
  +        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)
  +    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);
  +            treeWalk(child, theElements);
           }            
       }
   }    
  
  
  
  1.12      +22 -10    
jakarta-velocity/src/java/org/apache/velocity/anakia/XPathTool.java
  
  Index: XPathTool.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/anakia/XPathTool.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- XPathTool.java    2001/08/07 22:30:15     1.11
  +++ XPathTool.java    2001/08/08 04:30:47     1.12
  @@ -88,10 +88,25 @@
    *   $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:[EMAIL PROTECTED]";>bob mcwhirter</a>
    * @author <a href="mailto:[EMAIL PROTECTED]";>Jon S. Stevens</a>
  - * @version $Id: XPathTool.java,v 1.11 2001/08/07 22:30:15 geirm Exp $
  + * @author <a href="mailto:[EMAIL PROTECTED]";>Attila Szegedi</a>
  + * @version $Id: XPathTool.java,v 1.12 2001/08/08 04:30:47 jon Exp $
    */
   public class XPathTool
   {
  @@ -113,12 +128,11 @@
        *
        * @return A list of selected nodes
        */
  -    public List applyTo(String xpathSpec,
  +    public NodeList applyTo(String xpathSpec,
                           Document doc)
       {
           //RuntimeSingleton.info("XPathTool::applyTo(String, Document)");
  -        XPath xpath = new XPath( xpathSpec );
  -        return xpath.applyTo( doc );
  +        return new NodeList(XPathCache.getXPath(xpathSpec).applyTo( doc ), false);
       }
   
       /**
  @@ -129,12 +143,11 @@
        *
        * @return A list of selected nodes
        */
  -    public List applyTo(String xpathSpec,
  +    public NodeList applyTo(String xpathSpec,
                           Element elem)
       {
           //RuntimeSingleton.info("XPathTool::applyTo(String, Element)");
  -        XPath xpath = new XPath(xpathSpec);
  -        return xpath.applyTo( elem );
  +        return new NodeList(XPathCache.getXPath(xpathSpec).applyTo( elem ), false);
       }
   
       /**
  @@ -145,12 +158,11 @@
        *
        * @return A list of selected nodes
        */
  -    public List applyTo(String xpathSpec,
  +    public NodeList applyTo(String xpathSpec,
                           List nodeSet)
       {
           //RuntimeSingleton.info("XPathTool::applyTo(String, List)");
  -        XPath xpath = new XPath(xpathSpec);
  -        return xpath.applyTo( nodeSet );
  +        return new NodeList(XPathCache.getXPath(xpathSpec).applyTo( nodeSet ), 
false);
       }
   }
   
  
  
  
  1.1                  
jakarta-velocity/src/java/org/apache/velocity/anakia/AnakiaElement.java
  
  Index: AnakiaElement.java
  ===================================================================
  package org.apache.velocity.anakia;
  
  /*
   * 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 org.jdom.Element;
  import org.jdom.Namespace;
  import org.jdom.output.XMLOutputter;
  import com.werken.xpath.XPath;
  import java.util.List;
  
  /**
   * A JDOM {@link Element} that is tailored for Anakia needs. It has
   * {@link #selectNodes(String}} method as well as a {@link #toString()} that
   * outputs the XML serialized form of the element. This way it acts in much the
   * same way as a single-element {@link NodeList} would.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Attila Szegedi</a>
   * @version $Id: AnakiaElement.java,v 1.1 2001/08/08 04:30:47 jon Exp $
   */
  public class AnakiaElement extends Element
  {
      private static final XMLOutputter DEFAULT_OUTPUTTER = new XMLOutputter();
  
      /**
       * <p>
       * This will create a new <code>AnakiaElement</code>
       *   with the supplied (local) name, and define
       *   the <code>{@link Namespace}</code> to be used.
       * If the provided namespace is null, the element will have 
       * no namespace.
       * </p>
       *
       * @param name <code>String</code> name of element.
       * @namespace <code>Namespace</code> to put element in.
       */
      public AnakiaElement(String name, Namespace namespace)
      {
          super(name, namespace);
      }
  
      /**
       * <p>
       *  This will create an <code>AnakiaElement</code> in no
       *    <code>{@link Namespace}</code>.
       * </p>
       *
       * @param name <code>String</code> name of element.
       */
      public AnakiaElement(String name)
      {
          super(name);
      }
  
      /**
       * <p>
       *  This will create a new <code>AnakiaElement</code> with
       *    the supplied (local) name, and specifies the URI
       *    of the <code>{@link Namespace}</code> the <code>Element</code>
       *    should be in, resulting it being unprefixed (in the default
       *    namespace).
       * </p>
       *
       * @param name <code>String</code> name of element.
       * @param uri <code>String</code> URI for <code>Namespace</code> element
       *        should be in.
       */
      public AnakiaElement(String name, String uri)
      {
          super(name, uri);
      }
  
      /**
       * <p>
       *  This will create a new <code>AnakiaElement</code> with
       *    the supplied (local) name, and specifies the prefix and URI
       *    of the <code>{@link Namespace}</code> the <code>Element</code>
       *    should be in.
       * </p>
       *
       * @param name <code>String</code> name of element.
       * @param uri <code>String</code> URI for <code>Namespace</code> element
       *        should be in.
       */
      public AnakiaElement(String name, String prefix, String uri)
      {
          super(name, prefix, uri);
      }
      
      /**
       * Applies an XPath expression to this element 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 xpathExpression 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 element. It can be empty.
       */
      public NodeList selectNodes(String xpathExpression)
      {
          return new NodeList(XPathCache.getXPath(xpathExpression).applyTo(this), 
false);
      }
  
      /**
       * Returns the XML serialized form of this element, as produced by the default
       * {@link XMLOutputter}.
       */
      public String toString()
      {
          return DEFAULT_OUTPUTTER.outputString(this);
      }
      
      /**
       * <p>
       * This returns the full content of the element as a NodeList which
       * may contain objects of type <code>String</code>, <code>Element</code>,
       * <code>Comment</code>, <code>ProcessingInstruction</code>,
       * <code>CDATA</code>, and <code>EntityRef</code>.  
       * The List returned is "live" in document order and modifications 
       * to it affect the element's actual contents.  Whitespace content is 
       * returned in its entirety.
       * </p>
       *
       * @return a <code>List</code> containing the mixed content of the
       *         element: may contain <code>String</code>,
       *         <code>{@link Element}</code>, <code>{@link Comment}</code>,
       *         <code>{@link ProcessingInstruction}</code>,
       *         <code>{@link CDATA}</code>, and
       *         <code>{@link EntityRef}</code> objects.
       */
      public List getContent()
      {
          return new NodeList(super.getContent(), false);
      }
      
      /**
       * <p>
       * This returns a <code>NodeList</code> of all the child elements
       * nested directly (one level deep) within this element, as 
       * <code>Element</code> objects.  If this target element has no nested 
       * elements, an empty List is returned.  The returned list is "live"
       * in document order and changes to it affect the element's actual 
       * contents.
       * </p>
       * <p>
       * This performs no recursion, so elements nested two levels
       *   deep would have to be obtained with:
       * <pre>
       * <code>
       *   Iterator itr = currentElement.getChildren().iterator();
       *   while (itr.hasNext()) {
       *     Element oneLevelDeep = (Element)nestedElements.next();
       *     List twoLevelsDeep = oneLevelDeep.getChildren();
       *     // Do something with these children
       *   }
       * </code>
       * </pre>
       * </p>
       *
       * @return list of child <code>Element</code> objects for this element
       */
      public List getChildren()
      {
          return new NodeList(super.getChildren(), false);
      }
  
      /**
       * <p>
       * This returns a <code>NodeList</code> of all the child elements
       * nested directly (one level deep) within this element with the given
       * local name and belonging to no namespace, returned as 
       * <code>Element</code> objects.  If this target element has no nested 
       * elements with the given name outside a namespace, an empty List 
       * is returned.  The returned list is "live" in document order
       * and changes to it affect the element's actual contents.
       * </p>
       * <p>
       * Please see the notes for <code>{@link #getChildren}</code>
       * for a code example.
       * </p>
       *
       * @param name local name for the children to match
       * @return all matching child elements
       */
      public List getChildren(String name)
      {
          return new NodeList(super.getChildren(name));
      }
  
      /**
       * <p>
       * This returns a <code>NodeList</code> of all the child elements
       * nested directly (one level deep) within this element with the given
       * local name and belonging to the given Namespace, returned as 
       * <code>Element</code> objects.  If this target element has no nested 
       * elements with the given name in the given Namespace, an empty List 
       * is returned.  The returned list is "live" in document order
       * and changes to it affect the element's actual contents.
       * </p>
       * <p>
       * Please see the notes for <code>{@link #getChildren}</code>
       * for a code example.
       * </p>
       *
       * @param name local name for the children to match
       * @param ns <code>Namespace</code> to search within
       * @return all matching child elements
       */
      public List getChildren(String name, Namespace ns)
      {
          return new NodeList(super.getChildren(name, ns));
      }
  
      /**
       * <p>
       * This returns the complete set of attributes for this element, as a 
       * <code>NodeList</code> of <code>Attribute</code> objects in no particular 
       * order, or an empty list if there are none.  
       * The returned list is "live" and changes to it affect the 
       * element's actual attributes.
       * </p>
       *
       * @return attributes for the element
       */
      public List getAttributes()
      {
          return new NodeList(super.getAttributes());
      }
  }
  
  
  
  1.1                  
jakarta-velocity/src/java/org/apache/velocity/anakia/AnakiaJDOMFactory.java
  
  Index: AnakiaJDOMFactory.java
  ===================================================================
  package org.apache.velocity.anakia;
  
  /*
   * 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 org.jdom.Element;
  import org.jdom.Namespace;
  import org.jdom.input.DefaultJDOMFactory;
  
  /**
   * A customized JDOMFactory for Anakia that produces {@link AnakiaElement}
   * instances instead of ordinary JDOM {@link Element} instances.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Attila Szegedi</a>
   * @version $Id: AnakiaJDOMFactory.java,v 1.1 2001/08/08 04:30:47 jon Exp $
   */
  class AnakiaJDOMFactory extends DefaultJDOMFactory
  {
      AnakiaJDOMFactory()
      {
      }
  
      public Element element(String name, Namespace namespace)
      {
          return new AnakiaElement(name, namespace);
      }
  
      public Element element(String name)
      {
          return new AnakiaElement(name);
      }
  
      public Element element(String name, String uri)
      {
          return new AnakiaElement(name, uri);
      }
  
      public Element element(String name, String prefix, String uri)
      {
          return new AnakiaElement(name, prefix, uri);
      }
  }
  
  
  
  1.1                  
jakarta-velocity/src/java/org/apache/velocity/anakia/NodeList.java
  
  Index: NodeList.java
  ===================================================================
  package org.apache.velocity.anakia;
  
  /*
   * 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 com.werken.xpath.XPath;
  import java.io.Writer;
  import java.io.IOException;
  import java.io.StringWriter;
  import java.util.*;
  import org.jdom.*;
  import org.jdom.output.*;
  
  /**
   * 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:[EMAIL PROTECTED]";>Attila Szegedi</a>
   * @version $Id: NodeList.java,v 1.1 2001/08/08 04:30:47 jon Exp $
   */
  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.
       */
      public NodeList(Document document)
      {
          this((Object)document);
      }
  
      /**
       * Creates a node list that holds a single {@link Element} node.
       */
      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.
       */
      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).
       */
      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 String)
                  {
                      DEFAULT_OUTPUTTER.output(node.toString(), 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.
       * @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.
       */
      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 xpathExpression 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
  
      public boolean add(Object o)
      {
          return nodes.add(o);
      }
  
      public void add(int index, Object o)
      {
          nodes.add(index, o);
      }
  
      public boolean addAll(Collection c)
      {
          return nodes.addAll(c);
      }
  
      public boolean addAll(int index, Collection c)
      {
          return nodes.addAll(index, c);
      }
  
      public void clear()
      {
          nodes.clear();
      }
  
      public boolean contains(Object o)
      {
          return nodes.contains(o);
      }
  
      public boolean containsAll(Collection c)
      {
          return nodes.containsAll(c);
      }
  
      public Object get(int index)
      {
          return nodes.get(index);
      }
  
      public int indexOf(Object o)
      {
          return nodes.indexOf(o);
      }
  
      public boolean isEmpty()
      {
          return nodes.isEmpty();
      }
  
      public Iterator iterator()
      {
          return nodes.iterator();
      }
  
      public int lastIndexOf(Object o)
      {
          return nodes.lastIndexOf(o);
      }
  
      public ListIterator listIterator()
      {
          return nodes.listIterator();
      }
  
      public ListIterator listIterator(int index)
      {
          return nodes.listIterator(index);
      }
  
      public Object remove(int index)
      {
          return nodes.remove(index);
      }
  
      public boolean remove(Object o)
      {
          return nodes.remove(o);
      }
  
      public boolean removeAll(Collection c)
      {
          return nodes.removeAll(c);
      }
  
      public boolean retainAll(Collection c)
      {
          return nodes.retainAll(c);
      }
  
      public Object set(int index, Object o)
      {
          return nodes.set(index, o);
      }
  
      public int size()
      {
          return nodes.size();
      }
  
      public List subList(int fromIndex, int toIndex)
      {
          return new NodeList(nodes.subList(fromIndex, toIndex));
      }
  
      public Object[] toArray()
      {
          return nodes.toArray();
      }
  
      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
      {
          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("\"");            
          }
      }
  }
  
  
  
  1.1                  
jakarta-velocity/src/java/org/apache/velocity/anakia/XPathCache.java
  
  Index: XPathCache.java
  ===================================================================
  package org.apache.velocity.anakia;
  
  /*
   * 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 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:[EMAIL PROTECTED]";>Attila Szegedi</a>
   * @version $Id: XPathCache.java,v 1.1 2001/08/08 04:30:47 jon Exp $
   */
  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;
      }
  }
  
  
  

Reply via email to