View Javadoc

1   /*
2   This file is part of the xframe software package
3   hosted at http://xframe.sourceforge.net
4   
5   Copyright (c) 2003 Kurt Riede.
6   
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11  
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16  
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  */
21  package net.sf.xframe.xsddoc.util;
22  
23  import org.w3c.dom.NamedNodeMap;
24  import org.w3c.dom.Node;
25  import org.w3c.dom.NodeList;
26  
27  /***
28   * DOM Utility methods.
29   *
30   * @author <a href="mailto:kriede@users.sourceforge.net">Kurt Riede</a>
31   */
32  public final class DomUtil {
33  
34      /***
35       * Private default constructor to prevent instantiation.
36       */
37      private DomUtil() {
38      }
39  
40      /***
41       * Returns the first child node that is an element (type == ELEMENT_NODE).
42       *
43       * @param node the parent node
44       * @return the first child element or <code>null</code> if non available
45       */
46      public static Node getFirstElementChild(final Node node) {
47          final NodeList children = node.getChildNodes();
48          for (int i = 0; i < children.getLength(); i++) {
49              final Node child = children.item(i);
50              if (child.getNodeType() == Node.ELEMENT_NODE) {
51                  return child;
52              }
53          }
54          return null;
55      }
56  
57      /***
58       * Returns the value of a named attribute of a given node.
59       *
60       * @param node an element node
61       * @param name the name of an attribute
62       * @return the attributes value or <code>null</code> if the attribute doesn't exist.
63       */
64      public static String getAttributeValue(final Node node, final String name) {
65          try {
66              return node.getAttributes().getNamedItem(name).getNodeValue();
67          } catch (NullPointerException e) {
68              return null;
69          }
70      }
71  
72      /***
73       * Removes all duplicate children from a given node.
74       *
75       * @param parent the parent node of the children to process.
76       * @return the given node
77       */
78      public static Node removeDuplicates(final Node parent) {
79          if (parent == null) {
80           return null;
81          }
82          final NodeList children = parent.getChildNodes();
83          for (int i = children.getLength() - 1; i >= 0; i--) {
84              final Node child = children.item(i);
85              if (child.getNodeType() == Node.ELEMENT_NODE) {
86                  if (hasDuplicate(children, child)) {
87                      parent.removeChild(child);
88                  }
89              }
90          }
91          return parent;
92      }
93  
94      /***
95       * Checks if a node has a duplicate within a given NodeList.
96       * The node itself might be contained in the list, but is ignored in the
97       * check.
98       *
99       * @param children the node list to search in for duplicates
100      * @param node the node to compare with
101      * @return <code>true</code> if a duplicate is found, else <code>false</code>
102      */
103     private static boolean hasDuplicate(final NodeList children, final Node node) {
104         for (int i = 0; i < children.getLength(); i++) {
105             final Node child = children.item(i);
106             if (child != node && child.getNodeType() == Node.ELEMENT_NODE) {
107                 if (equals(node, child)) {
108                     return true;
109                 }
110             }
111         }
112         return false;
113     }
114 
115     /***
116      * Checks if two nodes are equal.
117      * Two nodes are considered equal, if all the following conditions are valid:
118      * <ul>
119      * <li>both, node1 and node2 are not <code>null</code></li>
120      * <li>the names are equal</li>
121      * <li>all attributes of node1 are available in node2 and have the same value</li>
122      * </ul>
123      * <p>Text nodes are not compared.</p>
124      * <p></p>
125      *
126      * @param node1 a node to compare
127      * @param node2 another node to compare with
128      * @return <code>true</code> if the two nodes are equal,
129      *         else <code>false</code>
130      */
131     private static boolean equals(final Node node1, final Node node2) {
132         if (node1 == null || node2 == null) {
133             return false;
134         }
135         if (!node1.getNodeName().equals(node2.getNodeName())) {
136             return false;
137         }
138         final NamedNodeMap attributes = node1.getAttributes();
139         for (int i = 0; i < attributes.getLength(); i++) {
140             final Node attribute1 = attributes.item(i);
141             final NamedNodeMap attributes2 = node2.getAttributes();
142             if (attributes2 == null) {
143                 return false; // no attributes available in node2, but expected
144             }
145             final Node attribute2 = node2.getAttributes().getNamedItem(attribute1.getNodeName());
146             if (attribute2 == null) {
147                 return false; // attribute missing in node2
148             }
149             if (!StringUtil.equals(attribute1.getNodeValue(), attribute2.getNodeValue())) {
150                 return false; // attribute values are not equal
151             }
152         }
153         return true; // no difference found so far: assume equality
154     }
155 }