001 /*
002 * Created on Apr 3, 2009
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 *
014 * Copyright @2009 the original author or authors.
015 */
016 package org.fest.swing.junit.xml;
017
018 import static org.fest.util.Objects.HASH_CODE_PRIME;
019 import static org.fest.util.Objects.hashCodeFor;
020 import static org.fest.util.Strings.concat;
021
022 import org.w3c.dom.*;
023
024 /**
025 * Understands a DOM-based XML element. This class is intended for internal use only. It is just a thin wrapper around
026 * a DOM <code>{@link Element}</code>. It only provides the necessary functionality needed by the FEST-Swing JUnit
027 * extension.
028 *
029 * @author Alex Ruiz
030 */
031 public class XmlNode {
032
033 private final Element target;
034
035 /**
036 * Creates a new </code>{@link XmlNode}</code>.
037 * @param target the underlying DOM element.
038 */
039 protected XmlNode(Element target) {
040 this.target = target;
041 }
042
043 /**
044 * Creates and adds a new XML node to this node.
045 * @param name the name of the node to add.
046 * @return the created node.
047 */
048 public XmlNode addNewNode(String name) {
049 return new XmlNode(createAndAddChild(name));
050 }
051
052 /**
053 * Creates and adds a new XML node to this node.
054 * @param name the name of the node to add.
055 * @param attributes the attributes of the node to add.
056 * @return the created node.
057 */
058 public XmlNode addNewNode(String name, XmlAttributes attributes) {
059 Element e = createAndAddChild(name);
060 for (XmlAttribute a : attributes) addAttribute(e, a);
061 return new XmlNode(e);
062 }
063
064 private Element createAndAddChild(String name) {
065 Element e = document().createElement(name);
066 target.appendChild(e);
067 return e;
068 }
069
070 /**
071 * Adds a CDATA section to this node.
072 * @param data the data for the CDATA section to create.
073 */
074 public void addCdata(String data) {
075 CDATASection s = document().createCDATASection(data);
076 target.appendChild(s);
077 }
078
079 /**
080 * Adds a text node to this node.
081 * @param text the text of the new text node.
082 */
083 public void addText(String text) {
084 Text textNode = document().createTextNode(text);
085 target.appendChild(textNode);
086 }
087
088 private Document document() {
089 return target.getOwnerDocument();
090 }
091
092 /**
093 * Adds an attribute to this node.
094 * @param a the attribute to add.
095 */
096 public void addAttribute(XmlAttribute a) {
097 addAttribute(target, a);
098 }
099
100 /**
101 * Adds one or more attributes to this node.
102 * @param attributes the attribute(s) to add to this node.
103 */
104 public void addAttributes(XmlAttribute...attributes) {
105 for (XmlAttribute a : attributes) addAttribute(target, a);
106 }
107
108 private static void addAttribute(Element e, XmlAttribute a) {
109 e.setAttribute(a.name(), a.value());
110 }
111
112 /**
113 * Returns the underlying DOM <code>{@link Element}</code>.
114 * @return the underlying DOM element.
115 */
116 public Element target() { return target; }
117
118 /**
119 * Returns the parent node of this node.
120 * @return the parent node of this node.
121 */
122 public XmlNode parentNode() {
123 return xmlNodeFrom(target.getParentNode());
124 }
125
126 /**
127 * Returns the number of children in this node.
128 * @return the number of children in this node.
129 */
130 public int size() {
131 return target.getChildNodes().getLength();
132 }
133
134 /**
135 * Returns the child at the given index.
136 * @param index the given index.
137 * @return the child at the given index.
138 */
139 public XmlNode child(int index) {
140 return xmlNodeFrom(target.getChildNodes().item(index));
141 }
142
143 private static XmlNode xmlNodeFrom(Node n) {
144 if (!(n instanceof Element)) return null;
145 return new XmlNode((Element)n);
146 }
147
148 /**
149 * Returns the value of the given attribute, or an empty <code>String</code> if this node does not contain an
150 * attribute with the given name.
151 * @param name the name of the attribute we are looking for.
152 * @return the value of the attribute with the given name, or an empty <code>String</code> if this node does not
153 * contain a matching attribute.
154 */
155 public String valueOfAttribute(String name) {
156 return target.getAttribute(name);
157 }
158
159 /**
160 * Returns the name of this node.
161 * @return the name of this node.
162 */
163 public String name() {
164 return target.getNodeName();
165 }
166
167 /**
168 * Returns the text content of this node.
169 * @return the text content of this node.
170 */
171 public String text() {
172 return target.getTextContent();
173 }
174
175 /**
176 * Returns the number of attributes in this node.
177 * @return the number of attributes in this node.
178 */
179 public int attributeCount() {
180 return target.getAttributes().getLength();
181 }
182
183 @Override public boolean equals(Object obj) {
184 if (this == obj) return true;
185 if (obj == null) return false;
186 if (getClass() != obj.getClass()) return false;
187 XmlNode other = (XmlNode) obj;
188 return target.isEqualNode(other.target);
189 }
190
191 @Override public int hashCode() {
192 int result = 1;
193 result = HASH_CODE_PRIME * result + hashCodeFor(name());
194 return result;
195 }
196
197 @Override public String toString() {
198 return concat(
199 getClass().getSimpleName(), "[",
200 "target=", target, "]"
201 );
202 }
203 }