/*
* Copyright 2004-2009 the original author or authors.
*
* 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.compass.core.util.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
* This class has a bunch of utility methods to work with configuration objects.
*/
public class ConfigurationHelperUtil {
/**
* Private constructor to block instantiation.
*/
private ConfigurationHelperUtil() {
}
/**
* Convert a DOM Element tree into a configuration tree.
*/
public static ConfigurationHelper toConfiguration(final Element element) {
final PlainConfigurationHelper configuration = new PlainConfigurationHelper(element.getNodeName(), "dom-created");
final NamedNodeMap attributes = element.getAttributes();
final int length = attributes.getLength();
for (int i = 0; i < length; i++) {
final Node node = attributes.item(i);
final String name = node.getNodeName();
final String value = node.getNodeValue();
configuration.setAttribute(name, value);
}
boolean flag = false;
String content = "";
final NodeList nodes = element.getChildNodes();
final int count = nodes.getLength();
for (int i = 0; i < count; i++) {
final Node node = nodes.item(i);
if (node instanceof Element) {
final ConfigurationHelper child = toConfiguration((Element) node);
configuration.addChild(child);
} else if (node instanceof CharacterData) {
final CharacterData data = (CharacterData) node;
content += data.getData();
flag = true;
}
}
if (flag) {
configuration.setValue(content);
}
return configuration;
}
/**
* Convert a configuration tree into a DOM Element tree.
*/
public static Element toElement(final ConfigurationHelper configuration) {
try {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document document = builder.newDocument();
return createElement(document, configuration);
} catch (final ParserConfigurationException pce) {
throw new IllegalStateException(pce.toString());
}
}
/**
* Test to see if two Configuration's can be considered the same. Name,
* value, attributes and children are test. The <b>order</b> of children is
* not taken into consideration for equality.
*/
public static boolean equals(final ConfigurationHelper c1, final ConfigurationHelper c2) {
return c1.getName().equals(c2.getName()) && areValuesEqual(c1, c2) && areAttributesEqual(c1, c2)
&& areChildrenEqual(c1, c2);
}
/**
* Return true if the children of both configurations are equal.
*/
private static boolean areChildrenEqual(final ConfigurationHelper c1, final ConfigurationHelper c2) {
final ConfigurationHelper[] kids1 = c1.getChildren();
final ArrayList kids2 = new ArrayList(Arrays.asList(c2.getChildren()));
if (kids1.length != kids2.size()) {
return false;
}
for (int i = 0; i < kids1.length; i++) {
if (!findMatchingChild(kids1[i], kids2)) {
return false;
}
}
return kids2.isEmpty() ? true : false;
}
/**
* Return true if find a matching child and remove child from list.
*/
private static boolean findMatchingChild(final ConfigurationHelper c, final ArrayList matchAgainst) {
final Iterator i = matchAgainst.iterator();
while (i.hasNext()) {
if (equals(c, (ConfigurationHelper) i.next())) {
i.remove();
return true;
}
}
return false;
}
/**
* Return true if the attributes of both configurations are equal.
*/
private static boolean areAttributesEqual(final ConfigurationHelper c1, final ConfigurationHelper c2) {
final String[] names1 = c1.getAttributeNames();
final String[] names2 = c2.getAttributeNames();
if (names1.length != names2.length) {
return false;
}
for (int i = 0; i < names1.length; i++) {
final String name = names1[i];
final String value1 = c1.getAttribute(name, null);
final String value2 = c2.getAttribute(name, null);
if (!value1.equals(value2)) {
return false;
}
}
return true;
}
/**
* Return true if the values of two configurations are equal.
*/
private static boolean areValuesEqual(final ConfigurationHelper c1, final ConfigurationHelper c2) {
final String value1 = c1.getValue(null);
final String value2 = c2.getValue(null);
return (value1 == null && value2 == null) || (value1 != null && value1.equals(value2));
}
/**
* Create an DOM {@link Element} from a {@link ConfigurationHelper} object.
*/
private static Element createElement(final Document document, final ConfigurationHelper configuration) {
final Element element = document.createElement(configuration.getName());
final String content = configuration.getValue(null);
if (null != content) {
final Text child = document.createTextNode(content);
element.appendChild(child);
}
final String[] names = configuration.getAttributeNames();
for (int i = 0; i < names.length; i++) {
final String name = names[i];
final String value = configuration.getAttribute(name, null);
element.setAttribute(name, value);
}
final ConfigurationHelper[] children = configuration.getChildren();
for (int i = 0; i < children.length; i++) {
final Element child = createElement(document, children[i]);
element.appendChild(child);
}
return element;
}
}