View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.commons.configuration;
    19
    20  import java.util.Iterator;
    21
    22  import org.apache.commons.configuration.HierarchicalConfiguration.Node;
    23  import org.xml.sax.Attributes;
    24  import org.xml.sax.helpers.AttributesImpl;
    25
    26  /***
    27   * <p>A specialized SAX2 XML parser that "parses" hierarchical
    28   * configuration objects.</p>
    29   * <p>This class mimics to be a SAX conform XML parser. Instead of parsing
    30   * XML documents it processes a <code>Configuration</code> object and
    31   * generates SAX events for the single properties defined there. This enables
    32   * the whole world of XML processing for configuration objects.</p>
    33   * <p>The <code>HierarchicalConfiguration</code> object to be parsed can be
    34   * specified using a constructor or the <code>setConfiguration()</code> method.
    35   * This object will be processed by the <code>parse()</code> methods. Note
    36   * that these methods ignore their argument.</p>
    37   *
    38   * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
    39   * @version $Id: HierarchicalConfigurationXMLReader.java 439648 2006-09-02 20:42:10Z oheger $
    40   */
    41  public class HierarchicalConfigurationXMLReader extends ConfigurationXMLReader
    42  {
    43      /*** Stores the configuration object to be parsed.*/
    44      private HierarchicalConfiguration configuration;
    45
    46      /***
    47       * Creates a new instance of
    48       * <code>HierarchicalConfigurationXMLReader</code>.
    49       */
    50      public HierarchicalConfigurationXMLReader()
    51      {
    52          super();
    53      }
    54
    55      /***
    56       * Creates a new instance of
    57       * <code>HierarchicalConfigurationXMLReader</code> and sets the
    58       * configuration to be parsed.
    59       *
    60       * @param config the configuration object
    61       */
    62      public HierarchicalConfigurationXMLReader(HierarchicalConfiguration config)
    63      {
    64          this();
    65          setConfiguration(config);
    66      }
    67
    68      /***
    69       * Returns the configuration object to be parsed.
    70       *
    71       * @return the configuration object to be parsed
    72       */
    73      public HierarchicalConfiguration getConfiguration()
    74      {
    75          return configuration;
    76      }
    77
    78      /***
    79       * Sets the configuration object to be parsed.
    80       *
    81       * @param config the configuration object to be parsed
    82       */
    83      public void setConfiguration(HierarchicalConfiguration config)
    84      {
    85          configuration = config;
    86      }
    87
    88      /***
    89       * Returns the configuration object to be processed.
    90       *
    91       * @return the actual configuration object
    92       */
    93      public Configuration getParsedConfiguration()
    94      {
    95          return getConfiguration();
    96      }
    97
    98      /***
    99       * Processes the actual configuration object to generate SAX parsing events.
    100      */
    101     protected void processKeys()
    102     {
    103         getConfiguration().getRoot().visit(new SAXVisitor(), null);
    104     }
    105
    106     /***
    107      * A specialized visitor class for generating SAX events for a
    108      * hierarchical node structure.
    109      *
    110      */
    111     class SAXVisitor extends HierarchicalConfiguration.NodeVisitor
    112     {
    113         /*** Constant for the attribute type.*/
    114         private static final String ATTR_TYPE = "CDATA";
    115
    116         /***
    117          * Visits the specified node after its children have been processed.
    118          *
    119          * @param node the actual node
    120          * @param key the key of this node
    121          */
    122         public void visitAfterChildren(Node node, ConfigurationKey key)
    123         {
    124             if (!isAttributeNode(node))
    125             {
    126                 fireElementEnd(nodeName(node));
    127             }
    128         }
    129
    130         /***
    131          * Visits the specified node.
    132          *
    133          * @param node the actual node
    134          * @param key the key of this node
    135          */
    136         public void visitBeforeChildren(Node node, ConfigurationKey key)
    137         {
    138             if (!isAttributeNode(node))
    139             {
    140                 fireElementStart(nodeName(node), fetchAttributes(node));
    141
    142                 if (node.getValue() != null)
    143                 {
    144                     fireCharacters(node.getValue().toString());
    145                 }
    146             }
    147         }
    148
    149         /***
    150          * Checks if iteration should be terminated. This implementation stops
    151          * iteration after an exception has occurred.
    152          *
    153          * @return a flag if iteration should be stopped
    154          */
    155         public boolean terminate()
    156         {
    157             return getException() != null;
    158         }
    159
    160         /***
    161          * Returns an object with all attributes for the specified node.
    162          *
    163          * @param node the actual node
    164          * @return an object with all attributes of this node
    165          */
    166         protected Attributes fetchAttributes(Node node)
    167         {
    168             AttributesImpl attrs = new AttributesImpl();
    169
    170             for (Iterator it = node.getAttributes().iterator(); it.hasNext();)
    171             {
    172                 Node child = (Node) it.next();
    173                 if (child.getValue() != null)
    174                 {
    175                     String attr = child.getName();
    176                     attrs.addAttribute(NS_URI, attr, attr, ATTR_TYPE, child.getValue().toString());
    177                 }
    178             }
    179
    180             return attrs;
    181         }
    182
    183         /***
    184          * Helper method for determining the name of a node. If a node has no
    185          * name (which is true for the root node), the specified default name
    186          * will be used.
    187          *
    188          * @param node the node to be checked
    189          * @return the name for this node
    190          */
    191         private String nodeName(Node node)
    192         {
    193             return (node.getName() == null) ? getRootName() : node.getName();
    194         }
    195
    196         /***
    197          * Checks if the specified node is an attribute node. In the node
    198          * hierarchy attributes are stored as normal child nodes, but with
    199          * special names.
    200          *
    201          * @param node the node to be checked
    202          * @return a flag if this is an attribute node
    203          */
    204         private boolean isAttributeNode(Node node)
    205         {
    206             return node.isAttribute();
    207         }
    208     }
    209 }