Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  // Copyright 2006, 2007, 2008, 2009, 2010 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.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
 package org.apache.tapestry5.dom;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
An element that will render with a begin tag and attributes, a body, and an end tag. Also acts as a factory for enclosed Element, Text and Comment nodes.

TODO: Support for CDATA nodes. Do we need Entity nodes?

 
 public final class Element extends Node
 {
 
     private final String name;
 
     private Node firstChild;
 
     private Node lastChild;
 
     private Attribute firstAttribute;
 
     private final Document document;
 
     private static final String CLASS_ATTRIBUTE = "class";

    
URI of the namespace which contains the element. A quirk in XML is that the element may be in a namespace it defines itself, so resolving the namespace to a prefix must wait until render time (since the Element is created before the namespaces for it are defined).
 
     private final String namespace;
 
     private Map<StringStringnamespaceToPrefix;

    
Constructor for a root element.
 
     Element(Document containerString namespaceString name)
     {
         super(null);
 
          = container;
         this. = namespace;
         this. = name;
     }

    
Constructor for a nested element.
 
     Element(Element parentString namespaceString name)
     {
         super(parent);
 
         this. = namespace;
         this. = name;
 
          = null;
     }
 
     @Override
     public Document getDocument()
     {
         return  != null ?  : super.getDocument();
     }

    
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 Node.getContainer() instead
 
     public Element getParent()
     {
        return ;
    }

    
Adds an attribute to the element, but only if the attribute name does not already exist.

Parameters:
name the name of the attribute to add
value the value for the attribute. A value of null is allowed, and no attribute will be added to the element.
    public Element attribute(String nameString value)
    {
        return attribute(nullnamevalue);
    }

    
Adds a namespaced attribute to the element, but only if the attribute name does not already exist.

Parameters:
namespace the namespace to contain the attribute, or null
name the name of the attribute to add
value the value for the attribute. A value of null is allowed, and no attribute will be added to the element.
    public Element attribute(String namespaceString nameString value)
    {
        assert InternalUtils.isNonBlank(name);
        updateAttribute(namespacenamevaluefalse);
        return this;
    }
    private void updateAttribute(String namespaceString nameString valueboolean force)
    {
        if (!force && value == nullreturn;
        Attribute prior = null;
        Attribute cursor = ;
        while (cursor != null)
        {
            if (cursor.matches(namespacename))
            {
                if (!forcereturn;
                if (value != null)
                {
                    cursor.value = value;
                    return;
                }
                // Remove this Attribute node from the linked list
                if (prior == null)
                     = cursor.nextAttribute;
                else
                    prior.nextAttribute = cursor.nextAttribute;
                return;
            }
            prior = cursor;
            cursor = cursor.nextAttribute;
        }
        //  Don't add a Attribute if the value is null.
        if (value == nullreturn;
         = new Attribute(thisnamespacenamevalue);
    }


    
Convenience for invoking attribute(java.lang.String,java.lang.String) multiple times.

Parameters:
namesAndValues alternating attribute names and attribute values
    public Element attributes(String... namesAndValues)
    {
        int i = 0;
        while (i < namesAndValues.length)
        {
            String name = namesAndValues[i++];
            String value = namesAndValues[i++];
            attribute(namevalue);
        }
        return this;
    }

    
Forces changes to a number of attributes. The new attributes overwrite previous values. Overriding an attribute's value to null will remove the attribute entirely.
    public Element forceAttributes(String... namesAndValues)
    {
        int i = 0;
        while (i < namesAndValues.length)
        {
            String name = namesAndValues[i++];
            String value = namesAndValues[i++];
            updateAttribute(namevaluetrue);
        }
        return this;
    }

    
Creates and returns a new Element node as a child of this node.

Parameters:
name the name of the element to create
namesAndValues alternating attribute names and attribute values
    public Element element(String nameString... namesAndValues)
    {
        assert InternalUtils.isNonBlank(name);
        Element child = newChild(new Element(thisnullname));
        child.attributes(namesAndValues);
        return child;
    }

    
Creates and returns a new Element within a namespace as a child of this node.

Parameters:
namespace namespace to contain the element, or null
name element name to create within the namespace
Returns:
the newly created element
    public Element elementNS(String namespaceString name)
    {
        assert InternalUtils.isNonBlank(name);
        return newChild(new Element(thisnamespacename));
    }
    public Element elementAt(int indexString nameString... namesAndValues)
    {
        assert InternalUtils.isNonBlank(name);
        Element child = new Element(thisnullname);
        child.attributes(namesAndValues);
        insertChildAt(indexchild);
        return child;
    }

    
Adds the comment and returns this element for further construction.
    public Element comment(String text)
    {
        newChild(new Comment(thistext));
        return this;
    }

    
Adds the raw text and returns this element for further construction.
    public Element raw(String text)
    {
        newChild(new Raw(thistext));
        return this;
    }

    
Adds and returns a new text node (the text node is returned so that Text.write(java.lang.String) or [@link Text.writef(java.lang.String,java.lang.Object[]) may be invoked .

Parameters:
text initial text for the node
Returns:
the new Text node
    public Text text(String text)
    {
        return newChild(new Text(thistext));
    }

    
Adds and returns a new CDATA node.

Parameters:
content the content to be rendered by the node
Returns:
the newly created node
    public CData cdata(String content)
    {
        return newChild(new CData(thiscontent));
    }
    private <T extends Node> T newChild(T child)
    {
        addChild(child);
        return child;
    }
    @Override
    void toMarkup(Document documentPrintWriter writerMap<StringStringcontainerNamespacePrefixToURI)
    {
        Map<StringStringlocalNamespacePrefixToURI = createNamespaceURIToPrefix(containerNamespacePrefixToURI);
        MarkupModel markupModel = document.getMarkupModel();
        StringBuilder builder = new StringBuilder();
        String prefixedElementName = toPrefixedName(localNamespacePrefixToURI);
        builder.append("<").append(prefixedElementName);
        // Output order used to be alpha sorted, but now it tends to be the inverse
        // of the order in which attributes were added.
        for (Attribute attr = attr != nullattr = attr.nextAttribute)
        {
            attr.render(markupModelbuilderlocalNamespacePrefixToURI);
        }
        // Next, emit namespace declarations for each namespace.
        List<Stringnamespaces = InternalUtils.sortedKeys();
        for (String namespace : namespaces)
        {
            if (namespace.equals(.)) continue;
            String prefix = .get(namespace);
            builder.append(" xmlns");
            if (!prefix.equals(""))
            {
                builder.append(":").append(prefix);
            }
            builder.append("=");
            builder.append(markupModel.getAttributeQuote());
            markupModel.encodeQuoted(namespacebuilder);
            builder.append(markupModel.getAttributeQuote());
        }
        EndTagStyle style = markupModel.getEndTagStyle();
        boolean hasChildren = hasChildren();
        String close = (!hasChildren && style == .) ? "/>" : ">";
        builder.append(close);
        writer.print(builder.toString());
        if (hasChildrenwriteChildMarkup(documentwriterlocalNamespacePrefixToURI);
        // 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.
        if (style == .return;
        if (hasChildren || style == .)
        {
            // TAP5-471: Avoid use of printf().
            writer.print("</");
            writer.print(prefixedElementName);
            writer.print(">");
        }
    }
    String toPrefixedName(Map<StringStringnamespaceURIToPrefixString namespaceString name)
    {
        if (namespace == null || namespace.equals("")) return name;
        if (namespace.equals(.)) return "xml:" + name;
        String prefix = namespaceURIToPrefix.get(namespace);
        // This should never happen, because namespaces are automatically defined as needed.
        if (prefix == null)
            throw new IllegalArgumentException(
                    String.format("No prefix has been defined for namespace '%s'."namespace));
        // The empty string indicates the default namespace which doesn't use a prefix.
        if (prefix.equals("")) return name;
        return prefix + ":" + name;
    }

    
Tries to find an element under this element (including itself) whose id is specified. Performs a width-first search of the document tree.

Parameters:
id the value of the id attribute of the element being looked for
Returns:
the element if found. null if not found.
    public Element getElementById(String id)
    {
        assert id != null;
        LinkedList<Elementqueue = CollectionFactory.newLinkedList();
        queue.add(this);
        while (!queue.isEmpty())
        {
            Element e = queue.removeFirst();
            String elementId = e.getAttribute("id");
            if (id.equals(elementId)) return e;
            for (Element child : e.childElements())
            {
                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.

Parameters:
path
Returns:
    public Element find(String path)
    {
        assert InternalUtils.isNonBlank(path);
        Element search = this;
        for (String name : TapestryInternalUtils.splitPath(path))
        {
            search = search.findChildWithElementName(name);
            if (search == nullbreak;
        }
        return search;
    }
    private Element findChildWithElementName(String name)
    {
        for (Element child : childElements())
        {
            if (child.getName().equals(name))
                return child;
        }
        // Not found.
        return null;
    }
    private Iterable<ElementchildElements()
    {
        return new Iterable<Element>()
        {
            public Iterator<Elementiterator()
            {
                return new Iterator<Element>()
                {
                    private Node cursor = ;
                    {
                        advance();
                    }
                    private void advance()
                    {
                        while ( != null)
                        {
                            if ( instanceof Elementreturn;
                             = .;
                        }
                    }
                    public boolean hasNext()
                    {
                        return  != null;
                    }
                    public Element next()
                    {
                        Element result = (Element;
                         = .;
                        advance();
                        return result;
                    }
                    public void remove()
                    {
                        throw new UnsupportedOperationException("remove() not supported.");
                    }
                };
            }
        };
    }
    public String getAttribute(String attributeName)
    {
        for (Attribute attr = attr != nullattr = attr.nextAttribute)
        {
            if (attr.getName().equalsIgnoreCase(attributeName))
                return attr.value;
        }
        return null;
    }
    public String getName()
    {
        return ;
    }

    
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.

Parameters:
className one or more CSS class names
Returns:
the element for further configuration
    public Element addClassName(String... className)
    {
        String classes = getAttribute();
        StringBuilder builder = new StringBuilder();
        if (classes != nullbuilder.append(classes);
        for (String name : className)
        {
            if (builder.length() > 0) builder.append(" ");
            builder.append(name);
        }
        forceAttributes(builder.toString());
        return this;
    }

    
Defines a namespace for this element, mapping a URI to a prefix. This will affect how namespaced elements and attributes nested within the element are rendered, and will also cause xmlns: attributes (to define the namespace and prefix) to be rendered.

Parameters:
namespace URI of the namespace
namespacePrefix prefix
Returns:
this element
    public Element defineNamespace(String namespaceString namespacePrefix)
    {
        assert namespace != null;
        assert namespacePrefix != null;
        if (namespace.equals(.))
            return this;
        if ( == null)
             = CollectionFactory.newMap();
        .put(namespacenamespacePrefix);
        return this;
    }

    
Returns the namespace for this element (which is typically a URL). The namespace may be null.
    public String getNamespace()
    {
        return ;
    }

    
Removes an element; the element's children take the place of the node within its container.
    public void pop()
    {
        // Have to be careful because we'll be  modifying the underlying list of children
        // as we work, so we need a copy of the children.
        List<NodechildrenCopy = CollectionFactory.newList(getChildren());
        for (Node child : childrenCopy)
        {
            child.moveBefore(this);
        }
        remove();
    }

    
Removes all children from this element.

Returns:
the element, for method chaining
    public Element removeChildren()
    {
         = null;
         = null;
        return this;
    }

    
Creates the URI to namespace prefix map for this element, which reflects namespace mappings from containing elements. In addition, automatic namespaces are defined for any URIs that are not explicitly mapped (this occurs sometimes in Ajax partial render scenarios).

Returns:
a mapping from namespace URI to namespace prefix
    private Map<StringStringcreateNamespaceURIToPrefix(Map<StringStringcontainerNamespaceURIToPrefix)
    {
        MapHolder holder = new MapHolder(containerNamespaceURIToPrefix);
        holder.putAll();
        // result now contains all the mappings, including this element's.
        // Add a mapping for the element's namespace.
        if (InternalUtils.isNonBlank())
        {
            // Add the namespace for the element as the default namespace.
            if (!holder.getResult().containsKey())
            {
                defineNamespace("");
                holder.put("");
            }
        }
        // And for any attributes that have a namespace.
        for (Attribute attr = attr != nullattr = attr.nextAttribute)
            addMappingIfNeeded(holderattr.getNamespace());
        return holder.getResult();
    }
    private void addMappingIfNeeded(MapHolder holderString namespace)
    {
        if (InternalUtils.isBlank(namespace)) return;
        Map<StringStringcurrent = holder.getResult();
        if (current.containsKey(namespace)) return;
        // A missing namespace.
        Set<Stringprefixes = CollectionFactory.newSet(holder.getResult().values());
        // A clumsy way to find a unique id for the new namespace.
        int i = 0;
        while (true)
        {
            String prefix = "ns" + i;
            if (!prefixes.contains(prefix))
            {
                defineNamespace(namespaceprefix);
                holder.put(namespaceprefix);
                return;
            }
            i++;
        }
    }
    @Override
    protected Map<StringStringgetNamespaceURIToPrefix()
    {
        MapHolder holder = new MapHolder();
        List<Elementelements = CollectionFactory.newList(this);
        Element cursor = ;
        while (cursor != null)
        {
            elements.add(cursor);
            cursor = cursor.container;
        }
        // Reverse the list, so that later elements will overwrite earlier ones.
        Collections.reverse(elements);
        for (Element e : elements)
            holder.putAll(e.namespaceToPrefix);
        return holder.getResult();
    }

    
Returns true if the element has no children, or has only text children that contain only whitespace.

Since:
5.1.0.0
    public boolean isEmpty()
    {
        List<Nodechildren = getChildren();
        if (children.isEmpty()) return true;
        for (Node n : children)
        {
            if (n instanceof Text)
            {
                Text t = (Textn;
                if (t.isEmpty()) continue;
            }
            // Not a text node, or a non-empty text node, then the element isn't empty.
            return false;
        }
        return true;
    }

    
Depth-first visitor traversal of this Element and its Element children. The traversal order is the same as render order.

Parameters:
visitor callback
Since:
5.1.0.0
    public void visit(Visitor visitor)
    {
        Stack<Elementqueue = CollectionFactory.newStack();
        queue.push(this);
        while (!queue.isEmpty())
        {
            Element e = queue.pop();
            visitor.visit(e);
            e.queueChildren(queue);
        }
    }
    private void queueChildren(Stack<Elementqueue)
    {
        if ( == nullreturn;
        List<ElementchildElements = CollectionFactory.newList();
        for (Node cursor = cursor != nullcursor = cursor.nextSibling)
        {
            if (cursor instanceof Element)
                childElements.add((Elementcursor);
        }
        Collections.reverse(childElements);
        for (Element e : childElements)
            queue.push(e);
    }
    void addChild(Node child)
    {
        child.container = this;
        if ( == null)
        {
             = child;
             = child;
            return;
        }
        . = child;
         = child;
    }
    void insertChildAt(int indexNode newChild)
    {
        newChild.container = this;
        if (index < 1)
        {
            newChild.nextSibling = ;
             = newChild;
        }
        else
        {
            Node cursor = ;
            for (int i = 1; i < indexi++)
            {
                cursor = cursor.nextSibling;
            }
            newChild.nextSibling = cursor.nextSibling;
            cursor.nextSibling = newChild;
        }
        if (index < 1)
             = newChild;
        if (newChild.nextSibling == null)
             = newChild;
    }
    boolean hasChildren()
    {
        return  != null;
    }
    void writeChildMarkup(Document documentPrintWriter writerMap<StringStringnamespaceURIToPrefix)
    {
        Node cursor = ;
        while (cursor != null)
        {
            cursor.toMarkup(documentwriternamespaceURIToPrefix);
            cursor = cursor.nextSibling;
        }
    }

    

Returns:
the concatenation of the String representations Node.toString() of its children.
    public final String getChildMarkup()
    {
        PrintOutCollector collector = new PrintOutCollector();
        writeChildMarkup(getDocument(), collector.getPrintWriter(), null);
        return collector.getPrintOut();
    }

    
Returns an unmodifiable list of children for this element. Only Elements will have children. Also, note that unlike W3C DOM, attributes are not represented as Nodes.

Returns:
unmodifiable list of children nodes
    @SuppressWarnings("unchecked")
    public List<NodegetChildren()
    {
        List<Noderesult = CollectionFactory.newList();
        Node cursor = ;
        while (cursor != null)
        {
            result.add(cursor);
            cursor = cursor.nextSibling;
        }
        return result;
    }
    void remove(Node node)
    {
        Node prior = null;
        Node cursor = ;
        while (cursor != null)
        {
            if (cursor == node)
            {
                Node afterNode = node.nextSibling;
                if (prior != null)
                    prior.nextSibling = afterNode;
                else
                     = afterNode;
                // If node was the final node in the element then handle deletion.
                // It's even possible node was the only node in the container.
                if ( == node)
                {
                     = prior != null ? prior : null;
                }
                return;
            }
            prior = cursor;
            cursor = cursor.nextSibling;
        }
        throw new IllegalArgumentException("Node to remove was not present as a child of this element.");
    }
    void insertChildBefore(Node existingNode node)
    {
        int index = indexOfNode(existing);
        node.container = this;
        insertChildAt(indexnode);
    }
    void insertChildAfter(Node existingNode node)
    {
        Node oldAfter = existing.nextSibling;
        existing.nextSibling = node;
        node.nextSibling = oldAfter;
        if (oldAfter == null)
             = node;
        node.container = this;
    }
    int indexOfNode(Node node)
    {
        int index = 0;
        Node cursor = ;
        while (cursor != null)
        {
            if (node == cursorreturn index;
            cursor = cursor.nextSibling;
            index++;
        }
        throw new IllegalArgumentException("Node not a child of this element.");
    }

    
Returns the attributes for this Element as a (often empty) collection of Attributes. The order of the attributes within the collection is not specified. Modifying the collection will not affect the attributes (use forceAttributes(java.lang.String[]) to change existing attribute values, and attribute(java.lang.String,java.lang.String,java.lang.String) to add new attribute values.

Returns:
attribute collection
    {
        Collection<Attributeresult = CollectionFactory.newList();
        for (Attribute a = a != nulla = a.nextAttribute)
        {
            result.add(a);
        }
        return result;
    }
New to GrepCode? Check out our FAQ X