001/*
002 * Copyright (c) 2012, the Last.fm Java Project and Committers
003 * All rights reserved.
004 *
005 * Redistribution and use of this software in source and binary forms, with or without modification, are
006 * permitted provided that the following conditions are met:
007 *
008 * - Redistributions of source code must retain the above
009 *   copyright notice, this list of conditions and the
010 *   following disclaimer.
011 *
012 * - Redistributions in binary form must reproduce the above
013 *   copyright notice, this list of conditions and the
014 *   following disclaimer in the documentation and/or other
015 *   materials provided with the distribution.
016 *
017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
018 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
019 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
020 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
021 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
023 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
024 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
025 */
026package de.umass.xml;
027
028import java.util.ArrayList;
029import java.util.List;
030
031import org.w3c.dom.Element;
032import org.w3c.dom.Node;
033import org.w3c.dom.NodeList;
034
035/**
036 * <code>DomElement</code> wraps around an {@link Element} and provides convenience methods.
037 *
038 * @author Janni Kovacs
039 */
040public class DomElement {
041        private Element e;
042
043        /**
044         * Creates a new wrapper around the given {@link Element}.
045         *
046         * @param elem An w3c Element
047         */
048        public DomElement(Element elem) {
049                this.e = elem;
050        }
051
052        /**
053         * @return the original Element
054         */
055        public Element getElement() {
056                return e;
057        }
058
059        /**
060         * Tests if this element has an attribute with the specified name.
061         *
062         * @param name Name of the attribute.
063         * @return <code>true</code> if this element has an attribute with the specified name.
064         */
065        public boolean hasAttribute(String name) {
066                return e.hasAttribute(name);
067        }
068        
069        /**
070         * Returns the attribute value to a given attribute name or <code>null</code> if the attribute doesn't exist.
071         *
072         * @param name The attribute's name
073         * @return Attribute value or <code>null</code>
074         */
075        public String getAttribute(String name) {
076                return e.hasAttribute(name) ? e.getAttribute(name) : null;
077        }
078
079        /**
080         * @return the text content of the element
081         */
082        public String getText() {
083                // XXX e.getTextContent() doesn't exsist under Android (Lukasz Wisniewski)
084                /// getTextContent() is now available in at least Android 2.2 if not earlier, so we'll keep using that
085                // return e.hasChildNodes() ? e.getFirstChild().getNodeValue() : null;
086                return e.getTextContent();
087        }
088
089        /**
090         * Checks if this element has a child element with the given name.
091         *
092         * @param name The child's name
093         * @return <code>true</code> if this element has a child element with the given name
094         */
095        public boolean hasChild(String name) {
096                NodeList list = e.getElementsByTagName(name);
097                for (int i = 0, j = list.getLength(); i < j; i++) {
098                        Node item = list.item(i);
099                        if (item.getParentNode() == e)
100                                return true;
101                }
102                return false;
103        }
104
105        /**
106         * Returns the child element with the given name or <code>null</code> if it doesn't exist.
107         *
108         * @param name The child's name
109         * @return the child element or <code>null</code>
110         */
111        public DomElement getChild(String name) {
112                NodeList list = e.getElementsByTagName(name);
113                if (list.getLength() == 0)
114                        return null;
115                for (int i = 0, j = list.getLength(); i < j; i++) {
116                        Node item = list.item(i);
117                        if (item.getParentNode() == e)
118                                return new DomElement((Element) item);
119                }
120                return null;
121        }
122
123        /**
124         * Returns the text content of a child node with the given name. If no such child exists or the child
125         * does not have text content, <code>null</code> is returned.
126         *
127         * @param name The child's name
128         * @return the child's text content or <code>null</code>
129         */
130        public String getChildText(String name) {
131                DomElement child = getChild(name);
132                return child != null ? child.getText() : null;
133        }
134
135        /**
136         * @return all children of this element
137         */
138        public List<DomElement> getChildren() {
139                return getChildren("*");
140        }
141
142        /**
143         * Returns all children of this element with the given tag name.
144         *
145         * @param name The children's tag name
146         * @return all matching children
147         */
148        public List<DomElement> getChildren(String name) {
149                List<DomElement> l = new ArrayList<DomElement>();
150                NodeList list = e.getElementsByTagName(name);
151                for (int i = 0; i < list.getLength(); i++) {
152                        Node node = list.item(i);
153                        if (node.getParentNode() == e)
154                                l.add(new DomElement((Element) node));
155                }
156                return l;
157        }
158
159        /**
160         * Returns this element's tag name.
161         *
162         * @return the tag name
163         */
164        public String getTagName() {
165                return e.getTagName();
166        }
167}