001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.util.config;
018:
019: import java.util.ArrayList;
020: import java.util.Arrays;
021: import java.util.Iterator;
022:
023: import javax.xml.parsers.DocumentBuilder;
024: import javax.xml.parsers.DocumentBuilderFactory;
025: import javax.xml.parsers.ParserConfigurationException;
026:
027: import org.w3c.dom.CharacterData;
028: import org.w3c.dom.Document;
029: import org.w3c.dom.Element;
030: import org.w3c.dom.NamedNodeMap;
031: import org.w3c.dom.Node;
032: import org.w3c.dom.NodeList;
033: import org.w3c.dom.Text;
034:
035: /**
036: * This class has a bunch of utility methods to work with configuration objects.
037: */
038: public class ConfigurationHelperUtil {
039:
040: /**
041: * Private constructor to block instantiation.
042: */
043: private ConfigurationHelperUtil() {
044: }
045:
046: /**
047: * Convert a DOM Element tree into a configuration tree.
048: */
049: public static ConfigurationHelper toConfiguration(
050: final Element element) {
051: final XmlConfigurationHelper configuration = new XmlConfigurationHelper(
052: element.getNodeName(), "dom-created");
053: final NamedNodeMap attributes = element.getAttributes();
054: final int length = attributes.getLength();
055: for (int i = 0; i < length; i++) {
056: final Node node = attributes.item(i);
057: final String name = node.getNodeName();
058: final String value = node.getNodeValue();
059: configuration.setAttribute(name, value);
060: }
061: boolean flag = false;
062: String content = "";
063: final NodeList nodes = element.getChildNodes();
064: final int count = nodes.getLength();
065: for (int i = 0; i < count; i++) {
066: final Node node = nodes.item(i);
067: if (node instanceof Element) {
068: final ConfigurationHelper child = toConfiguration((Element) node);
069: configuration.addChild(child);
070: } else if (node instanceof CharacterData) {
071: final CharacterData data = (CharacterData) node;
072: content += data.getData();
073: flag = true;
074: }
075: }
076: if (flag) {
077: configuration.setValue(content);
078: }
079: return configuration;
080: }
081:
082: /**
083: * Convert a configuration tree into a DOM Element tree.
084: */
085: public static Element toElement(
086: final ConfigurationHelper configuration) {
087: try {
088: final DocumentBuilderFactory factory = DocumentBuilderFactory
089: .newInstance();
090: final DocumentBuilder builder = factory
091: .newDocumentBuilder();
092: final Document document = builder.newDocument();
093: return createElement(document, configuration);
094: } catch (final ParserConfigurationException pce) {
095: throw new IllegalStateException(pce.toString());
096: }
097: }
098:
099: /**
100: * Test to see if two Configuration's can be considered the same. Name,
101: * value, attributes and children are test. The <b>order</b> of children is
102: * not taken into consideration for equality.
103: */
104: public static boolean equals(final ConfigurationHelper c1,
105: final ConfigurationHelper c2) {
106: return c1.getName().equals(c2.getName())
107: && areValuesEqual(c1, c2) && areAttributesEqual(c1, c2)
108: && areChildrenEqual(c1, c2);
109: }
110:
111: /**
112: * Return true if the children of both configurations are equal.
113: */
114: private static boolean areChildrenEqual(
115: final ConfigurationHelper c1, final ConfigurationHelper c2) {
116: final ConfigurationHelper[] kids1 = c1.getChildren();
117: final ArrayList kids2 = new ArrayList(Arrays.asList(c2
118: .getChildren()));
119: if (kids1.length != kids2.size()) {
120: return false;
121: }
122: for (int i = 0; i < kids1.length; i++) {
123: if (!findMatchingChild(kids1[i], kids2)) {
124: return false;
125: }
126: }
127: return kids2.isEmpty() ? true : false;
128: }
129:
130: /**
131: * Return true if find a matching child and remove child from list.
132: */
133: private static boolean findMatchingChild(
134: final ConfigurationHelper c, final ArrayList matchAgainst) {
135: final Iterator i = matchAgainst.iterator();
136: while (i.hasNext()) {
137: if (equals(c, (ConfigurationHelper) i.next())) {
138: i.remove();
139: return true;
140: }
141: }
142: return false;
143: }
144:
145: /**
146: * Return true if the attributes of both configurations are equal.
147: */
148: private static boolean areAttributesEqual(
149: final ConfigurationHelper c1, final ConfigurationHelper c2) {
150: final String[] names1 = c1.getAttributeNames();
151: final String[] names2 = c2.getAttributeNames();
152: if (names1.length != names2.length) {
153: return false;
154: }
155: for (int i = 0; i < names1.length; i++) {
156: final String name = names1[i];
157: final String value1 = c1.getAttribute(name, null);
158: final String value2 = c2.getAttribute(name, null);
159: if (!value1.equals(value2)) {
160: return false;
161: }
162: }
163: return true;
164: }
165:
166: /**
167: * Return true if the values of two configurations are equal.
168: */
169: private static boolean areValuesEqual(final ConfigurationHelper c1,
170: final ConfigurationHelper c2) {
171: final String value1 = c1.getValue(null);
172: final String value2 = c2.getValue(null);
173: return (value1 == null && value2 == null)
174: || (value1 != null && value1.equals(value2));
175: }
176:
177: /**
178: * Create an DOM {@link Element} from a {@link ConfigurationHelper} object.
179: */
180: private static Element createElement(final Document document,
181: final ConfigurationHelper configuration) {
182: final Element element = document.createElement(configuration
183: .getName());
184: final String content = configuration.getValue(null);
185: if (null != content) {
186: final Text child = document.createTextNode(content);
187: element.appendChild(child);
188: }
189: final String[] names = configuration.getAttributeNames();
190: for (int i = 0; i < names.length; i++) {
191: final String name = names[i];
192: final String value = configuration.getAttribute(name, null);
193: element.setAttribute(name, value);
194: }
195: final ConfigurationHelper[] children = configuration
196: .getChildren();
197: for (int i = 0; i < children.length; i++) {
198: final Element child = createElement(document, children[i]);
199: element.appendChild(child);
200: }
201: return element;
202: }
203: }
|