You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/12/31 18:11:37 UTC

svn commit: r491446 - in /tapestry/tapestry5/tapestry-core/trunk/src: main/java/org/apache/tapestry/dom/ test/java/org/apache/tapestry/dom/

Author: hlship
Date: Sun Dec 31 09:11:36 2006
New Revision: 491446

URL: http://svn.apache.org/viewvc?view=rev&rev=491446
Log:
Add a limited ability to navigate and modify the DOM

Modified:
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Comment.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Document.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Element.java
    tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Node.java
    tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/dom/DOMTest.java

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Comment.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Comment.java?view=diff&rev=491446&r1=491445&r2=491446
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Comment.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Comment.java Sun Dec 31 09:11:36 2006
@@ -12,30 +12,30 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package org.apache.tapestry.dom;
-
-import java.io.PrintWriter;
-
-/**
- * A node that represents a comment within the DOM.
- * 
- * 
- */
-public final class Comment extends Node
-{
-    private String _comment;
-
-    Comment(Node container, String comment)
-    {
-        super(container);
-
-        _comment = comment;
-    }
-
-    @Override
-    public void toMarkup(PrintWriter writer)
-    {
-        writer.printf("<!-- %s -->", _comment);
-    }
-
-}
+package org.apache.tapestry.dom;
+
+import java.io.PrintWriter;
+
+/**
+ * A node that represents a comment within the DOM.
+ */
+public final class Comment extends Node
+{
+    private String _comment;
+
+    Comment(Node container, String comment)
+    {
+        super(container);
+
+        _comment = comment;
+    }
+
+    @Override
+    public void toMarkup(PrintWriter writer)
+    {
+        writer.print("<!-- ");
+        writer.print(_comment);
+        writer.print(" -->");
+    }
+
+}

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Document.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Document.java?view=diff&rev=491446&r1=491445&r2=491446
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Document.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Document.java Sun Dec 31 09:11:36 2006
@@ -16,6 +16,8 @@
 
 import java.io.PrintWriter;
 
+import org.apache.tapestry.ioc.internal.util.Defense;
+
 /**
  * The root node of a DOM.
  */
@@ -34,6 +36,31 @@
     Document getDocument()
     {
         return this;
+    }
+
+    /**
+     * Finds an element based on a path of element names.
+     * 
+     * @param path
+     *            slash separated series of element names
+     * @return the matching element, or null if not found
+     * @see Element#find(String)
+     */
+    public Element find(String path)
+    {
+        Defense.notBlank(path, "path");
+
+        if (_rootElement == null)
+            return null;
+
+        int slashx = path.indexOf("/");
+
+        String rootElementName = slashx < 0 ? path : path.substring(0, slashx);
+
+        if (!_rootElement.getName().equals(rootElementName))
+            return null;
+
+        return slashx < 0 ? _rootElement : _rootElement.find(path.substring(slashx + 1));
     }
 
     /** Builds with an instance of {@link DefaultMarkupModel}. */

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Element.java?view=diff&rev=491446&r1=491445&r2=491446
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Element.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Element.java Sun Dec 31 09:11:36 2006
@@ -14,16 +14,19 @@
 
 package org.apache.tapestry.dom;
 
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newLinkedList;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
 
 import java.io.PrintWriter;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.tapestry.ioc.internal.util.Defense;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
 
 /**
  * An element that will render with a begin tag and attributes, a body, and an end tag. Also acts as
@@ -132,6 +135,18 @@
         return child;
     }
 
+    public Element elementAt(int index, String name, String... namesAndValues)
+    {
+        notBlank(name, "name");
+
+        Element child = new Element(this, name);
+        child.attributes(namesAndValues);
+
+        insertChildAt(index, child);
+
+        return child;
+    }
+
     public Comment comment(String text)
     {
         return newChild(new Comment(this, text));
@@ -178,7 +193,7 @@
         writer.print(close);
 
         if (hasChildren)
-            writeChildXML(writer);
+            writeChildMarkup(writer);
 
         // Dangerous -- perhaps it should be an error for a tag of type OMIT to even have children!
         // We'll certainly be writing out unbalanced markup in that case.
@@ -192,6 +207,7 @@
 
     /**
      * Tries to find an element under this element (including itself) whose id is specified.
+     * Performs a width-first search of the document tree.
      * 
      * @param id
      *            the value of the id attribute of the element being looked for
@@ -200,37 +216,87 @@
     public Element getElementById(String id)
     {
         Defense.notNull(id, "id");
-        if (id.equals(getAttribute("id")))
-        {
-            return this;
-        }
-        for (Node child : getChildren())
+
+        LinkedList<Element> queue = newLinkedList();
+
+        queue.add(this);
+
+        while (!queue.isEmpty())
         {
-            if (child instanceof Element)
+            Element e = queue.removeFirst();
+
+            String elementId = e.getAttribute("id");
+
+            if (id.equals(elementId))
+                return e;
+
+            for (Node n : e.getChildren())
             {
-                Element elementChild = (Element) child;
-                Element searchResult = elementChild.getElementById(id);
-                if (searchResult != null)
-                {
-                    return searchResult;
-                }
+                Element child = n.asElement();
+
+                if (child != null)
+                    queue.addLast(child);
             }
         }
+
+        // Exhausted the entire tree
+
         return null;
+    }
 
+    /**
+     * Searchs for a child element with a particular name below this element. The path parameter is
+     * a slash separated series of element names.
+     * 
+     * @param path
+     * @return
+     */
+    public Element find(String path)
+    {
+        notBlank(path, "path");
+
+        Element search = this;
+
+        for (String name : path.split("/"))
+        {
+            search = search.findChildWithElementName(name);
+
+            if (search == null)
+                break;
+        }
+
+        return search;
     }
 
-    public String getAttribute(String attributeName)
+    private Element findChildWithElementName(String name)
     {
-        if (_attributes == null)
+        for (Node node : getChildren())
         {
-            return null;
+            Element child = node.asElement();
+
+            if (child != null && child.getName().equals(name))
+                return child;
         }
-        return _attributes.get(attributeName);
+
+        // Not found.
+
+        return null;
+    }
+
+    public String getAttribute(String attributeName)
+    {
+        return InternalUtils.get(_attributes, attributeName);
     }
 
     public String getName()
     {
         return _name;
+    }
+
+    /** All other implementations of Node return null except this one. */
+    @Override
+    Element asElement()
+    {
+        return this;
     }
 }

Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Node.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Node.java?view=diff&rev=491446&r1=491445&r2=491446
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Node.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/dom/Node.java Sun Dec 31 09:11:36 2006
@@ -47,7 +47,13 @@
         return _container;
     }
 
-    protected void addChild(Node child)
+    /** Returns the node as an {@link Element}, if it is an element. Returns null otherwise. */
+    Element asElement()
+    {
+        return null;
+    }
+
+    void addChild(Node child)
     {
         if (_children == null)
             _children = newList();
@@ -55,12 +61,20 @@
         _children.add(child);
     }
 
-    protected boolean hasChildren()
+    void insertChildAt(int index, Node child)
+    {
+        if (_children == null)
+            _children = newList();
+
+        _children.add(index, child);
+    }
+
+    boolean hasChildren()
     {
         return _children != null && !_children.isEmpty();
     }
 
-    protected void writeChildXML(PrintWriter writer)
+    void writeChildMarkup(PrintWriter writer)
     {
         if (_children == null)
             return;
@@ -75,7 +89,7 @@
     public String getChildText()
     {
         PrintOutCollector collector = new PrintOutCollector();
-        writeChildXML(collector.getPrintWriter());
+        writeChildMarkup(collector.getPrintWriter());
         return collector.getPrintOut();
     }
 

Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/dom/DOMTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/dom/DOMTest.java?view=diff&rev=491446&r1=491445&r2=491446
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/dom/DOMTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/dom/DOMTest.java Sun Dec 31 09:11:36 2006
@@ -237,7 +237,7 @@
         assertSame(e.getElementById("y"), e2);
         assertNull(e.getElementById("z"));
     }
-    
+
     @Test
     public void get_child_markup()
     {
@@ -247,5 +247,82 @@
         e1.text("123");
         assertEquals(e1.getChildText(), "123");
         assertEquals(e0.getChildText(), "<e1>123</e1>");
+    }
+
+    @Test
+    public void document_find_no_root_element()
+    {
+        Document d = new Document();
+
+        assertNull(d.find("does/not/matter"));
+    }
+
+    @Test
+    public void document_find_not_a_match()
+    {
+        Document d = new Document();
+
+        d.newRootElement("fred");
+
+        assertNull(d.find("barney"));
+        assertNull(d.find("wilma/betty"));
+    }
+
+    @Test
+    public void document_find_root_is_match()
+    {
+        Document d = new Document();
+
+        Element root = d.newRootElement("fred");
+
+        assertSame(d.find("fred"), root);
+    }
+
+    @Test
+    public void document_find_match()
+    {
+        Document d = new Document();
+
+        Element root = d.newRootElement("fred");
+
+        root.text("text");
+        Element barney = root.element("barney");
+        Element bambam = barney.element("bambam");
+
+        assertSame(d.find("fred/barney/bambam"), bambam);
+        assertSame(root.find("barney/bambam"), bambam);
+    }
+
+    @Test
+    public void document_find_no_match()
+    {
+        Document d = new Document();
+
+        Element root = d.newRootElement("fred");
+
+        root.text("text");
+        Element barney = root.element("barney");
+        barney.element("bambam");
+
+        assertNull(d.find("fred/barney/pebbles"));
+        assertNull(root.find("barney/pebbles"));
+    }
+
+    @Test
+    public void insert_element_at()
+    {
+        Document d = new Document(new XMLMarkupModel());
+
+        Element root = d.newRootElement("fred");
+
+        root.element("start");
+        root.element("end");
+
+        root.elementAt(1, "one").element("tiny");
+        root.elementAt(2, "two").element("bubbles");
+
+        assertEquals(
+                d.toString(),
+                "<fred><start/><one><tiny/></one><two><bubbles/></two><end/></fred>");
     }
 }