blob: b3c9c831a78cf271a87ae4141653a025938019c9 [file] [log] [blame]
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* 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.apache.commons.configuration;
import java.util.List;
import org.apache.commons.configuration.HierarchicalConfiguration.Node;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
/**
* <p>A specialized SAX2 XML parser that "parses" hierarchical
* configuration objects.</p>
* <p>This class mimics to be a SAX conform XML parser. Instead of parsing
* XML documents it processes a <code>Configuration</code> object and
* generates SAX events for the single properties defined there. This enables
* the whole world of XML processing for configuration objects.</p>
* <p>The <code>HierarchicalConfiguration</code> object to be parsed can be
* specified using a constructor or the <code>setConfiguration()</code> method.
* This object will be processed by the <code>parse()</code> methods. Note
* that these methods ignore their argument.</p>
*
* @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
* @version $Id: HierarchicalConfigurationXMLReader.java,v 1.5 2004/07/05 09:54:17 ebourg Exp $
*/
public class HierarchicalConfigurationXMLReader extends ConfigurationXMLReader
{
/** Stores the configuration object to be parsed.*/
private HierarchicalConfiguration configuration;
/**
* Creates a new instance of
* <code>HierarchicalConfigurationXMLReader</code>.
*/
public HierarchicalConfigurationXMLReader()
{
super();
}
/**
* Creates a new instance of
* <code>HierarchicalConfigurationXMLReader</code> and sets the
* configuration to be parsed.
*
* @param config the configuration object
*/
public HierarchicalConfigurationXMLReader(HierarchicalConfiguration config)
{
this();
setConfiguration(config);
}
/**
* Returns the configuration object to be parsed.
*
* @return the configuration object to be parsed
*/
public HierarchicalConfiguration getConfiguration()
{
return configuration;
}
/**
* Sets the configuration object to be parsed.
*
* @param config the configuration object to be parsed
*/
public void setConfiguration(HierarchicalConfiguration config)
{
configuration = config;
}
/**
* Returns the configuration object to be processed.
*
* @return the actual configuration object
*/
public Configuration getParsedConfiguration()
{
return getConfiguration();
}
/**
* Processes the actual configuration object to generate SAX parsing events.
*/
protected void processKeys()
{
getConfiguration().getRoot().visit(new SAXVisitor(), null);
}
/**
* A specialized visitor class for generating SAX events for a
* hierarchical node structure.
*
*/
class SAXVisitor extends HierarchicalConfiguration.NodeVisitor
{
/** Constant for the attribute type.*/
private static final String ATTR_TYPE = "CDATA";
/**
* Visits the specified node after its children have been processed.
*
* @param node the actual node
* @param key the key of this node
*/
public void visitAfterChildren(Node node, ConfigurationKey key)
{
if (!isAttributeNode(node))
{
fireElementEnd(nodeName(node));
}
}
/**
* Visits the specified node.
*
* @param node the actual node
* @param key the key of this node
*/
public void visitBeforeChildren(Node node, ConfigurationKey key)
{
if (!isAttributeNode(node))
{
fireElementStart(nodeName(node), fetchAttributes(node));
if (node.getValue() != null)
{
fireCharacters(node.getValue().toString());
}
}
}
/**
* Checks if iteration should be terminated. This implementation stops
* iteration after an exception has occurred.
*
* @return a flag if iteration should be stopped
*/
public boolean terminate()
{
return getException() != null;
}
/**
* Returns an object with all attributes for the specified node.
*
* @param node the actual node
* @return an object with all attributes of this node
*/
protected Attributes fetchAttributes(Node node)
{
AttributesImpl attrs = new AttributesImpl();
List children = node.getChildren();
for (int i = 0; i < children.size(); i++)
{
Node child = (Node) children.get(i);
if (isAttributeNode(child) && child.getValue() != null)
{
String attr = ConfigurationKey.attributeName(child.getName());
attrs.addAttribute(NS_URI, attr, attr, ATTR_TYPE, child.getValue().toString());
}
}
return attrs;
}
/**
* Helper method for determining the name of a node. If a node has no
* name (which is true for the root node), the specified default name
* will be used.
*
* @param node the node to be checked
* @return the name for this node
*/
private String nodeName(Node node)
{
return (node.getName() == null) ? getRootName() : node.getName();
}
/**
* Checks if the specified node is an attribute node. In the node
* hierarchy attributes are stored as normal child nodes, but with
* special names.
*
* @param node the node to be checked
* @return a flag if this is an attribute node
*/
private boolean isAttributeNode(Node node)
{
return ConfigurationKey.isAttributeKey(node.getName());
}
}
}