You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2009/03/04 03:18:01 UTC

svn commit: r749885 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/dom/ test/java/org/apache/tapestry5/dom/ test/java/org/apache/tapestry5/integration/ test/java/org/apache/tapestry5/internal/ test/java/org/apache/tape...

Author: hlship
Date: Wed Mar  4 02:17:59 2009
New Revision: 749885

URL: http://svn.apache.org/viewvc?rev=749885&view=rev
Log:
TAP5-550: Reduce eden space memory footprint by avoiding Lists and Maps within Elements

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/dom/DOMTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/DefaultValidationDecoratorTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/MarkupWriterImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/namespace_element_without_a_prefix.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/nested_elements.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/add_style_links.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/duplicate_scripts_ignored_first_media_wins.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/empty_document_with_scripts_at_top.txt
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/existing_head_used_if_present.txt

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/CData.java Wed Mar  4 02:17:59 2009
@@ -1,4 +1,4 @@
-// Copyright 2007, 2008 The Apache Software Foundation
+// Copyright 2007, 2008, 2009 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -25,7 +25,7 @@
 {
     private final String content;
 
-    public CData(Node container, String content)
+    public CData(Element container, String content)
     {
         super(container);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Comment.java Wed Mar  4 02:17:59 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2008 The Apache Software Foundation
+// Copyright 2006, 2008, 2009 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
 {
     private final String comment;
 
-    Comment(Node container, String comment)
+    Comment(Element container, String comment)
     {
         super(container);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Document.java Wed Mar  4 02:17:59 2009
@@ -144,8 +144,6 @@
 
             writer.print("?>\n");
         }
-
-        // TODO: lead-in comments, directives.
         if (dtd != null)
         {
             dtd.toMarkup(writer);
@@ -233,7 +231,7 @@
      */
     public Document comment(String text)
     {
-        newChild(new Comment(this, text));
+        newChild(new Comment(null, text));
 
         return this;
     }
@@ -245,21 +243,21 @@
      */
     public Document raw(String text)
     {
-        newChild(new Raw(this, text));
+        newChild(new Raw(null, text));
 
         return this;
     }
 
     /**
      * Adds and returns a new text node (the text node is returned so that {@link Text#write(String)} or [@link {@link
-     * Text#writef(String, Object[])} may be invoked .
+     * Text#writef(String, Object[])} may be invoked.
      *
      * @param text initial text for the node
      * @return the new Text node
      */
     public Text text(String text)
     {
-        return newChild(new Text(this, text));
+        return newChild(new Text(null, text));
     }
 
     /**
@@ -270,6 +268,6 @@
      */
     public CData cdata(String content)
     {
-        return newChild(new CData(this, content));
+        return newChild(new CData(null, content));
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Element.java Wed Mar  4 02:17:59 2009
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.dom;
 
 import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.util.PrintOutCollector;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.Defense;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -34,14 +35,19 @@
     class Attribute
     {
         private final String namespace;
+
         private final String name;
-        private final String value;
 
-        public Attribute(String namespace, String name, String value)
+        private String value;
+
+        private Attribute nextAttribute;
+
+        public Attribute(String namespace, String name, String value, Attribute nextAttribute)
         {
             this.namespace = namespace;
             this.name = name;
             this.value = value;
+            this.nextAttribute = nextAttribute;
         }
 
 
@@ -54,13 +60,21 @@
             model.encodeQuoted(value, builder);
             builder.append(model.getAttributeQuote());
         }
+
+        public boolean matches(String namespace, String name)
+        {
+            return TapestryInternalUtils.isEqual(this.namespace, namespace) &&
+                    this.name.equalsIgnoreCase(name);
+        }
     }
 
     private final String name;
 
-    private Map<String, Attribute> attributes;
+    private Node firstChild;
+
+    private Node lastChild;
 
-    private Element parent;
+    private Attribute firstAttribute;
 
     private final Document document;
 
@@ -80,7 +94,7 @@
      */
     Element(Document container, String namespace, String name)
     {
-        super(container);
+        super(null);
 
         document = container;
         this.namespace = namespace;
@@ -94,7 +108,6 @@
     {
         super(parent);
 
-        this.parent = parent;
         this.namespace = namespace;
         this.name = name;
 
@@ -109,10 +122,12 @@
 
     /**
      * Returns the containing element for this element. This will be null for the root element of a document.
+     *
+     * @deprecated since 5.1.0.1, use {@link Node#getContainer()} instead
      */
     public Element getParent()
     {
-        return parent;
+        return container;
     }
 
     /**
@@ -141,9 +156,16 @@
 
         if (value == null) return this;
 
-        if (attributes == null) attributes = CollectionFactory.newMap();
+        for (Attribute attr = firstAttribute; attr != null; attr = attr.nextAttribute)
+        {
+            if (attr.matches(namespace, name))
+            {
+                attr.value = value;
+                return this;
+            }
+        }
 
-        if (!attributes.containsKey(name)) attributes.put(name, new Attribute(namespace, name, value));
+        firstAttribute = new Attribute(namespace, name, value, firstAttribute);
 
         return this;
     }
@@ -173,8 +195,6 @@
      */
     public Element forceAttributes(String... namesAndValues)
     {
-        if (attributes == null) attributes = CollectionFactory.newMap();
-
         int i = 0;
 
         while (i < namesAndValues.length)
@@ -182,18 +202,39 @@
             String name = namesAndValues[i++];
             String value = namesAndValues[i++];
 
-            if (value == null)
-            {
-                attributes.remove(name);
-                continue;
-            }
+            removeAttribute(name);
 
-            attributes.put(name, new Attribute(null, name, value));
+            if (value != null)
+                attribute(null, name, value);
         }
 
         return this;
     }
 
+    private void removeAttribute(String name)
+    {
+        Attribute prior = null;
+        Attribute cursor = firstAttribute;
+
+        while (cursor != null)
+        {
+            if (cursor.name.equalsIgnoreCase(name))
+            {
+                Attribute next = cursor.nextAttribute;
+
+                if (prior == null)
+                    firstAttribute = next;
+                else
+                    prior.nextAttribute = next;
+
+                return;
+            }
+
+            prior = cursor;
+            cursor = cursor.nextAttribute;
+        }
+    }
+
     /**
      * Creates and returns a new Element node as a child of this node.
      *
@@ -301,13 +342,12 @@
 
         builder.append("<").append(prefixedElementName);
 
-        List<String> keys = InternalUtils.sortedKeys(attributes);
+        // Output order used to be alpha sorted, but now it tends to be the inverse
+        // of the order in which attributes were added.
 
-        for (String key : keys)
+        for (Attribute attr = firstAttribute; attr != null; attr = attr.nextAttribute)
         {
-            Attribute attribute = attributes.get(key);
-
-            attribute.render(markupModel, builder, localNamespacePrefixToURI);
+            attr.render(markupModel, builder, localNamespacePrefixToURI);
         }
 
         // Next, emit namespace declarations for each namespace.
@@ -405,11 +445,9 @@
 
             if (id.equals(elementId)) return e;
 
-            for (Node n : e.getChildren())
+            for (Element child : e.childElements())
             {
-                Element child = n.asElement();
-
-                if (child != null) queue.addLast(child);
+                queue.addLast(child);
             }
         }
 
@@ -444,11 +482,10 @@
 
     private Element findChildWithElementName(String name)
     {
-        for (Node node : getChildren())
+        for (Element child : childElements())
         {
-            Element child = node.asElement();
-
-            if (child != null && child.getName().equals(name)) return child;
+            if (child.getName().equals(name))
+                return child;
         }
 
         // Not found.
@@ -456,11 +493,64 @@
         return null;
     }
 
+    private Iterable<Element> childElements()
+    {
+        return new Iterable<Element>()
+        {
+            public Iterator<Element> iterator()
+            {
+                return new Iterator<Element>()
+                {
+                    private Node cursor = firstChild;
+
+                    {
+                        advance();
+                    }
+
+                    private void advance()
+                    {
+                        while (cursor != null)
+                        {
+                            if (cursor instanceof Element) return;
+
+                            cursor = cursor.nextSibling;
+                        }
+                    }
+
+                    public boolean hasNext()
+                    {
+                        return cursor != null;
+                    }
+
+                    public Element next()
+                    {
+                        Element result = (Element) cursor;
+
+                        cursor = cursor.nextSibling;
+
+                        advance();
+
+                        return result;
+                    }
+
+                    public void remove()
+                    {
+                        throw new UnsupportedOperationException("remove() not supported.");
+                    }
+                };
+            }
+        };
+    }
+
     public String getAttribute(String attributeName)
     {
-        Attribute attribute = InternalUtils.get(attributes, attributeName);
+        for (Attribute attr = firstAttribute; attr != null; attr = attr.nextAttribute)
+        {
+            if (attr.name.equalsIgnoreCase(attributeName))
+                return attr.value;
+        }
 
-        return attribute == null ? null : attribute.value;
+        return null;
     }
 
     public String getName()
@@ -469,15 +559,6 @@
     }
 
     /**
-     * All other implementations of Node return null except this one.
-     */
-    @Override
-    Element asElement()
-    {
-        return this;
-    }
-
-    /**
      * Adds one or more CSS class names to the "class" attribute. No check for duplicates is made. Note that CSS class
      * names are case insensitive on the client.
      *
@@ -565,7 +646,8 @@
      */
     public Element removeChildren()
     {
-        clearChildren();
+        firstChild = null;
+        lastChild = null;
 
         return this;
     }
@@ -602,11 +684,8 @@
 
         // And for any attributes that have a namespace.
 
-        if (attributes != null)
-        {
-            for (Attribute a : attributes.values())
-                addMappingIfNeeded(holder, a.namespace);
-        }
+        for (Attribute attr = firstAttribute; attr != null; attr = attr.nextAttribute)
+            addMappingIfNeeded(holder, attr.namespace);
 
         return holder.getResult();
     }
@@ -648,12 +727,12 @@
 
         List<Element> elements = CollectionFactory.newList(this);
 
-        Element cursor = parent;
+        Element cursor = container;
 
         while (cursor != null)
         {
             elements.add(cursor);
-            cursor = cursor.parent;
+            cursor = cursor.container;
         }
 
         // Reverse the list, so that later elements will overwrite earlier ones.
@@ -719,21 +798,182 @@
 
     private void queueChildren(Stack<Element> queue)
     {
-        List<Node> children = getChildren();
+        if (firstChild == null) return;
+
+        List<Element> childElements = CollectionFactory.newList();
+
+        for (Node cursor = firstChild; cursor != null; cursor = cursor.nextSibling)
+        {
+            if (cursor instanceof Element)
+                childElements.add((Element) cursor);
+        }
+
+        Collections.reverse(childElements);
+
+        for (Element e : childElements)
+            queue.push(e);
+    }
+
+    void addChild(Node child)
+    {
+        child.container = this;
+
+        if (lastChild == null)
+        {
+            firstChild = child;
+            lastChild = child;
+            return;
+        }
+
+        lastChild.nextSibling = child;
+        lastChild = child;
+    }
+
+    void insertChildAt(int index, Node newChild)
+    {
+        newChild.container = this;
+
+        if (index < 1)
+        {
+            newChild.nextSibling = firstChild;
+            firstChild = newChild;
+        }
+        else
+        {
+            Node cursor = firstChild;
+            for (int i = 1; i < index; i++)
+            {
+                cursor = cursor.nextSibling;
+            }
+
+
+            newChild.nextSibling = cursor.nextSibling;
+            cursor.nextSibling = newChild;
+        }
+
+        if (index < 1)
+            firstChild = newChild;
+
+        if (newChild.nextSibling == null)
+            lastChild = newChild;
+    }
+
+    boolean hasChildren()
+    {
+        return firstChild != null;
+    }
+
+    void writeChildMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
+    {
+        Node cursor = firstChild;
+
+        while (cursor != null)
+        {
+            cursor.toMarkup(document, writer, namespaceURIToPrefix);
 
-        int count = children.size();
+            cursor = cursor.nextSibling;
+        }
+    }
 
-        // Push them in reverse order to get the correct
-        // traversal: the lowest index child is traversed first.
+    /**
+     * @return the concatenation of the String representations {@link #toString()} of its children.
+     */
+    public final String getChildMarkup()
+    {
+        PrintOutCollector collector = new PrintOutCollector();
 
-        for (int i = count - 1; i >= 0; i--)
+        writeChildMarkup(getDocument(), collector.getPrintWriter(), null);
+
+        return collector.getPrintOut();
+    }
+
+    /**
+     * Returns an unmodifiable list of children for this element. Only {@link org.apache.tapestry5.dom.Element}s will
+     * have children.  Also, note that unlike W3C DOM, attributes are not represented as {@link
+     * org.apache.tapestry5.dom.Node}s.
+     *
+     * @return unmodifiable list of children nodes
+     */
+    @SuppressWarnings("unchecked")
+    public List<Node> getChildren()
+    {
+        List<Node> result = CollectionFactory.newList();
+        Node cursor = firstChild;
+
+        while (cursor != null)
         {
-            Node n = children.get(i);
+            result.add(cursor);
+            cursor = cursor.nextSibling;
+        }
 
-            if (n instanceof Element)
+        return result;
+    }
+
+    void remove(Node node)
+    {
+        Node prior = null;
+        Node cursor = firstChild;
+
+        while (cursor != null)
+        {
+            if (cursor == node)
             {
-                queue.push((Element) n);
+                Node afterNode = node.nextSibling;
+
+                if (prior != null)
+                    prior.nextSibling = afterNode;
+                else
+                    firstChild = afterNode;
+
+                if (afterNode == null)
+                    lastChild = afterNode;
+
+                return;
             }
+
+            prior = cursor;
+            cursor = cursor.nextSibling;
         }
+
+        throw new IllegalArgumentException("Node to remove was not present as a child of this element.");
+    }
+
+    void insertChildBefore(Node existing, Node node)
+    {
+        int index = indexOfNode(existing);
+
+        node.container = this;
+
+        insertChildAt(index, node);
     }
+
+    void insertChildAfter(Node existing, Node node)
+    {
+        Node oldAfter = existing.nextSibling;
+
+        existing.nextSibling = node;
+        node.nextSibling = oldAfter;
+
+        if (oldAfter == null)
+            lastChild = node;
+
+        node.container = this;
+    }
+
+    int indexOfNode(Node node)
+    {
+        int index = 0;
+        Node cursor = firstChild;
+
+        while (cursor != null)
+        {
+            if (node == cursor) return index;
+
+            cursor = cursor.nextSibling;
+            index++;
+        }
+
+        throw new IllegalArgumentException("Node not a child of this element.");
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Node.java Wed Mar  4 02:17:59 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,12 +15,9 @@
 package org.apache.tapestry5.dom;
 
 import org.apache.tapestry5.internal.util.PrintOutCollector;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.Defense;
 
 import java.io.PrintWriter;
-import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -28,29 +25,29 @@
  */
 public abstract class Node
 {
-    private Node container;
+    Element container;
 
     /**
-     * Child notes; only Element actually has children.  Attributes are modeled differently in this DOM than in
-     * traditional W3C Dom (where Attributes are another type of child node).
+     * Next node within containing element.
      */
-    private List<Node> children;
+    Node nextSibling;
 
     /**
      * Creates a new node, setting its container to the provided value. Container may also be null, but that is only
      * used for Document nodes (the topmost node of a DOM).
      *
-     * @param container
+     * @param container element containing this node
      */
-    protected Node(Node container)
+    protected Node(Element container)
     {
         this.container = container;
     }
 
     /**
-     * Returns the containing node for this node, or null if this node is the root element of the document.
+     * Returns the containing {@link org.apache.tapestry5.dom.Element} for this node, or null if this node is the root
+     * element of the document.
      */
-    public Node getContainer()
+    public Element getContainer()
     {
         return container;
     }
@@ -60,61 +57,6 @@
         return container.getDocument();
     }
 
-    /**
-     * Returns the node as an {@link org.apache.tapestry5.dom.Element}, if it is an element. Returns null otherwise.
-     */
-    Element asElement()
-    {
-        return null;
-    }
-
-    void addChild(Node child)
-    {
-        ensureChildren();
-
-        children.add(child);
-
-        child.container = this;
-    }
-
-    private void ensureChildren()
-    {
-        if (children == null) children = CollectionFactory.newList();
-    }
-
-    void insertChildAt(int index, Node child)
-    {
-        ensureChildren();
-
-        children.add(index, child);
-
-        child.container = this;
-    }
-
-    boolean hasChildren()
-    {
-        return children != null && !children.isEmpty();
-    }
-
-    void writeChildMarkup(Document document, PrintWriter writer, Map<String, String> namespaceURIToPrefix)
-    {
-        if (children == null) return;
-
-        for (Node child : children)
-            child.toMarkup(document, writer, namespaceURIToPrefix);
-    }
-
-    /**
-     * @return the concatenation of the String representations {@link #toString()} of its children.
-     */
-    public final String getChildMarkup()
-    {
-        PrintOutCollector collector = new PrintOutCollector();
-
-        writeChildMarkup(getDocument(), collector.getPrintWriter(), null);
-
-        return collector.getPrintOut();
-    }
 
     /**
      * Invokes {@link #toMarkup(PrintWriter)}, collecting output in a string, which is returned.
@@ -129,18 +71,6 @@
         return collector.getPrintOut();
     }
 
-    /**
-     * Returns an unmodifiable list of children for this node. Only {@link org.apache.tapestry5.dom.Element}s will have
-     * children.  Also, note that unlike W3C DOM, attributes are not represented as {@link
-     * org.apache.tapestry5.dom.Node}s.
-     *
-     * @return unmodifiable list of children nodes
-     */
-    @SuppressWarnings("unchecked")
-    public List<Node> getChildren()
-    {
-        return children == null ? Collections.EMPTY_LIST : Collections.unmodifiableList(children);
-    }
 
     /**
      * Writes the markup for this node to the writer.
@@ -174,7 +104,7 @@
 
         remove();
 
-        element.getContainer().insertChildBefore(element, this);
+        element.container.insertChildBefore(element, this);
 
         return this;
     }
@@ -192,7 +122,7 @@
 
         remove();
 
-        element.getContainer().insertChildAfter(element, this);
+        element.container.insertChildAfter(element, this);
 
         return this;
     }
@@ -253,56 +183,11 @@
      */
     public void remove()
     {
-        getContainer().remove(this);
+        container.remove(this);
 
         container = null;
     }
 
-
-    /**
-     * Removes a child node from this node.
-     */
-    void remove(Node node)
-    {
-        if (children == null || !children.remove(node))
-            throw new IllegalArgumentException("Node to remove was not present as a child of this node.");
-    }
-
-    private void insertChildBefore(Node existing, Node node)
-    {
-        int index = indexOfNode(existing);
-
-        children.add(index, node);
-
-        node.container = this;
-    }
-
-    private void insertChildAfter(Node existing, Node node)
-    {
-        int index = indexOfNode(existing);
-
-        children.add(index + 1, node);
-
-        node.container = this;
-    }
-
-
-    int indexOfNode(Node node)
-    {
-        ensureChildren();
-
-        int index = children.indexOf(node);
-
-        if (index < 0) throw new IllegalArgumentException("Existing element not a child of this node.");
-
-        return index;
-    }
-
-    void clearChildren()
-    {
-        children = null;
-    }
-
     /**
      * Wraps a node inside a new element.  The new element is created before the node, then the node is moved inside the
      * new element.
@@ -313,13 +198,10 @@
      */
     public Element wrap(String elementName, String... namesAndValues)
     {
-        Element containerElement = container.asElement();
-
-        int index = containerElement.indexOfNode(this);
+        int index = container.indexOfNode(this);
 
         // Insert the new element just before this node.
-        Element element =
-                containerElement.elementAt(index, elementName, namesAndValues);
+        Element element = container.elementAt(index, elementName, namesAndValues);
 
         // Move this node inside the new element.
         moveToTop(element);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Raw.java Wed Mar  4 02:17:59 2009
@@ -1,4 +1,4 @@
-// Copyright 2007, 2008 The Apache Software Foundation
+// Copyright 2007, 2008, 2009 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -24,7 +24,7 @@
 {
     private final String text;
 
-    Raw(Node container, String text)
+    Raw(Element container, String text)
     {
         super(container);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/dom/Text.java Wed Mar  4 02:17:59 2009
@@ -24,7 +24,7 @@
 {
     private final StringBuilder buffer;
 
-    Text(Node container, String text)
+    Text(Element container, String text)
     {
         super(container);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/dom/DOMTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/dom/DOMTest.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/dom/DOMTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/dom/DOMTest.java Wed Mar  4 02:17:59 2009
@@ -437,7 +437,7 @@
         root.attribute("alpha-only", "abcdef");
         root.attribute("entities", "\"<>&");
 
-        assertEquals(root.toString(), "<prime alpha-only=\"abcdef\" entities=\"&quot;&lt;&gt;&amp;\"/>");
+        assertEquals(root.toString(), "<prime entities=\"&quot;&lt;&gt;&amp;\" alpha-only=\"abcdef\"/>");
     }
 
     @Test
@@ -767,6 +767,5 @@
 
         assertListsEquals(elementNames, "parent", "child1", "child1a", "child1b", "child2", "child2a", "child2b",
                           "child2c");
-
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Wed Mar  4 02:17:59 2009
@@ -1607,10 +1607,12 @@
         // - AbstractTextField.isRequired() and the logic inside ComponentFieldValidator.isRequired()
 
         assertSourcePresent(
-                "[Before label for Value]<label for=\"value\" id=\"value:label\">Value</label>[After label for Value]",
-                "[Before field Value]", "[After field Value (optional)]",
-                "[Before label for Required Value]<label for=\"requiredValue\" id=\"requiredValue:label\">Required Value</label>[After label for Required Value]",
-                "[Before field Required Value]", "[After field Required Value (required)]");
+                "[Before label for Value]<label id=\"value:label\" for=\"value\">Value</label>[After label for Value]",
+                "[Before field Value]",
+                "[After field Value (optional)]",
+                "[Before label for Required Value]<label id=\"requiredValue:label\" for=\"requiredValue\">Required Value</label>[After label for Required Value]",
+                "[Before field Required Value]",
+                "[After field Required Value (required)]");
     }
 
     /**
@@ -1665,7 +1667,8 @@
 
         assertTextPresent("Editor for org.apache.tapestry5.integration.app1.data.Track");
 
-        assertSourcePresent("<label for=\"title\" id=\"title:label\">Title</label>");
+        assertText("//label[@id='title:label']", "Title");
+        assertAttribute("//label[@id='title:label']/@for", "title");
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/DefaultValidationDecoratorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/DefaultValidationDecoratorTest.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/DefaultValidationDecoratorTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/DefaultValidationDecoratorTest.java Wed Mar  4 02:17:59 2009
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2009 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -60,7 +60,9 @@
 
         decorator.insideLabel(field, e);
 
-        assertEquals(writer.toString(), "<?xml version=\"1.0\"?>\n<label accesskey=\"f\" class=\"t-error\"/>");
+        assertEquals(writer.toString(),
+                     "<?xml version=\"1.0\"?>\n" +
+                             "<label class=\"t-error\" accesskey=\"f\"/>");
 
         verify();
     }
@@ -84,7 +86,8 @@
 
         decorator.insideLabel(field, e);
 
-        assertEquals(writer.toString(), "<?xml version=\"1.0\"?>\n<label accesskey=\"f\" class=\"foo t-error\"/>");
+        assertEquals(writer.toString(), "<?xml version=\"1.0\"?>\n" +
+                "<label class=\"foo t-error\" accesskey=\"f\"/>");
 
         verify();
     }
@@ -109,7 +112,8 @@
         decorator.insideField(field);
 
         assertEquals(writer.toString(),
-                     "<?xml version=\"1.0\"?>\n<input class=\"foo t-error\" name=\"ex\" size=\"30\" type=\"text\" value=\"freddy\"/>");
+                     "<?xml version=\"1.0\"?>\n" +
+                             "<input class=\"foo t-error\" size=\"30\" value=\"freddy\" name=\"ex\" type=\"text\"/>");
 
         verify();
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/MarkupWriterImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/MarkupWriterImplTest.java?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/MarkupWriterImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/MarkupWriterImplTest.java Wed Mar  4 02:17:59 2009
@@ -156,7 +156,7 @@
         root.attribute("gnip", "gnop");
 
         assertEquals(w.toString(),
-                     "<root foo=\"bar\" gnip=\"gnop\">before child<nested>inner text</nested>after child</root>");
+                     "<root gnip=\"gnop\" foo=\"bar\">before child<nested>inner text</nested>after child</root>");
     }
 
     @Test
@@ -169,7 +169,7 @@
 
         // img is a tag with an end tag style of omit, so no close tag is written.
 
-        assertEquals(w.toString(), "<img height=\"20\" src=\"foo.png\" width=\"20\"/>");
+        assertEquals(w.toString(), "<img height=\"20\" width=\"20\" src=\"foo.png\"/>");
     }
 
     @Test
@@ -181,7 +181,7 @@
 
         w.attributes("foo", "bar", "gnip", "gnop");
 
-        assertEquals(w.toString(), "<root foo=\"bar\" gnip=\"gnop\"></root>");
+        assertEquals(w.toString(), "<root gnip=\"gnop\" foo=\"bar\"></root>");
     }
 
     @Test

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/namespace_element_without_a_prefix.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/namespace_element_without_a_prefix.txt?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/namespace_element_without_a_prefix.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/namespace_element_without_a_prefix.txt Wed Mar  4 02:17:59 2009
@@ -1,2 +1,2 @@
 <?xml version="1.0"?>
-<root xmlns="fredns"><child><barney betty:betty="b" simple="a" ns0:wilma="c" xmlns="barneyns" xmlns:betty="bettyns" xmlns:ns0="wilmans"/></child></root>
\ No newline at end of file
+<root xmlns="fredns"><child><barney ns0:wilma="c" betty:betty="b" simple="a" xmlns="barneyns" xmlns:betty="bettyns" xmlns:ns0="wilmans"/></child></root>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/nested_elements.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/nested_elements.txt?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/nested_elements.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/dom/nested_elements.txt Wed Mar  4 02:17:59 2009
@@ -1 +1 @@
-<population><person first-name="Fred" last-name="Flintstone"></person><person first-name="Barney" last-name="Rubble"></person></population>
\ No newline at end of file
+<population><person last-name="Flintstone" first-name="Fred"></person><person last-name="Rubble" first-name="Barney"></person></population>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/add_style_links.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/add_style_links.txt?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/add_style_links.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/add_style_links.txt Wed Mar  4 02:17:59 2009
@@ -1,2 +1,2 @@
 <?xml version="1.0"?>
-<html><head><link href="foo.css" rel="stylesheet" type="text/css"/><link href="bar/baz.css" media="print" rel="stylesheet" type="text/css"/></head><body><p>Ready to be updated with styles.</p></body></html>
+<html><head><link type="text/css" rel="stylesheet" href="foo.css"/><link media="print" type="text/css" rel="stylesheet" href="bar/baz.css"/></head><body><p>Ready to be updated with styles.</p></body></html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/duplicate_scripts_ignored_first_media_wins.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/duplicate_scripts_ignored_first_media_wins.txt?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/duplicate_scripts_ignored_first_media_wins.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/duplicate_scripts_ignored_first_media_wins.txt Wed Mar  4 02:17:59 2009
@@ -1,2 +1,2 @@
 <?xml version="1.0"?>
-<html><head><link href="foo.css" rel="stylesheet" type="text/css"/><link href="bar/baz.css" media="print" rel="stylesheet" type="text/css"/></head><body><p>Ready to be updated with styles.</p></body></html>
\ No newline at end of file
+<html><head><link type="text/css" rel="stylesheet" href="foo.css"/><link media="print" type="text/css" rel="stylesheet" href="bar/baz.css"/></head><body><p>Ready to be updated with styles.</p></body></html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/empty_document_with_scripts_at_top.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/empty_document_with_scripts_at_top.txt?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/empty_document_with_scripts_at_top.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/empty_document_with_scripts_at_top.txt Wed Mar  4 02:17:59 2009
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<html><head><link href="style.css" media="print" rel="stylesheet" type="text/css"/><script src="foo.js"/><script src="bar/baz.js"/></head><body><script>Tapestry.onDOMLoaded(function() {
+<html><head><link media="print" type="text/css" rel="stylesheet" href="style.css"/><script src="foo.js"/><script src="bar/baz.js"/></head><body><script>Tapestry.onDOMLoaded(function() {
 pageInitialization();
 });
 </script></body></html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/existing_head_used_if_present.txt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/existing_head_used_if_present.txt?rev=749885&r1=749884&r2=749885&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/existing_head_used_if_present.txt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/existing_head_used_if_present.txt Wed Mar  4 02:17:59 2009
@@ -1,2 +1,2 @@
 <?xml version="1.0"?>
-<html><head><link href="foo.css" rel="stylesheet" type="text/css"/><!-- existing head --></head><body>body content</body></html>
\ No newline at end of file
+<html><head><link type="text/css" rel="stylesheet" href="foo.css"/><!-- existing head --></head><body>body content</body></html>
\ No newline at end of file