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  package org.apache.commons.configuration.tree.xpath;
    18
    19  import java.util.Iterator;
    20  import java.util.List;
    21  import java.util.Locale;
    22
    23  import org.apache.commons.configuration.tree.ConfigurationNode;
    24  import org.apache.commons.jxpath.ri.Compiler;
    25  import org.apache.commons.jxpath.ri.QName;
    26  import org.apache.commons.jxpath.ri.compiler.NodeTest;
    27  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
    28  import org.apache.commons.jxpath.ri.model.NodeIterator;
    29  import org.apache.commons.jxpath.ri.model.NodePointer;
    30
    31  /***
    32   * <p>
    33   * A specific <code>NodePointer</code> implementation for configuration nodes.
    34   * </p>
    35   * <p>
    36   * This is needed for queries using JXPath.
    37   * </p>
    38   *
    39   * @since 1.3
    40   * @author Oliver Heger
    41   * @version $Id: ConfigurationNodePointer.java 439648 2006-09-02 20:42:10Z oheger $
    42   */
    43  class ConfigurationNodePointer extends NodePointer
    44  {
    45      /***
    46       * The serial version UID.
    47       */
    48      private static final long serialVersionUID = -1087475639680007713L;
    49
    50      /*** Stores the associated configuration node. */
    51      private ConfigurationNode node;
    52
    53      /***
    54       * Creates a new instance of <code>ConfigurationNodePointer</code>.
    55       *
    56       * @param node the node
    57       * @param locale the locale
    58       */
    59      public ConfigurationNodePointer(ConfigurationNode node, Locale locale)
    60      {
    61          super(null, locale);
    62          this.node = node;
    63      }
    64
    65      /***
    66       * Creates a new instance of <code>ConfigurationNodePointer</code> and
    67       * initializes it with its parent pointer.
    68       *
    69       * @param parent the parent pointer
    70       * @param node the associated node
    71       */
    72      public ConfigurationNodePointer(NodePointer parent, ConfigurationNode node)
    73      {
    74          super(parent);
    75          this.node = node;
    76      }
    77
    78      /***
    79       * Returns a flag whether this node is a leaf. This is the case if there are
    80       * no child nodes.
    81       *
    82       * @return a flag if this node is a leaf
    83       */
    84      public boolean isLeaf()
    85      {
    86          return node.getChildrenCount() < 1;
    87      }
    88
    89      /***
    90       * Returns a flag if this node is a collection. This is not the case.
    91       *
    92       * @return the collection flag
    93       */
    94      public boolean isCollection()
    95      {
    96          return false;
    97      }
    98
    99      /***
    100      * Returns this node's length. This is always 1.
    101      *
    102      * @return the node's length
    103      */
    104     public int getLength()
    105     {
    106         return 1;
    107     }
    108
    109     /***
    110      * Checks whether this node pointer refers to an attribute node. This method
    111      * checks the attribute flag of the associated configuration node.
    112      *
    113      * @return the attribute flag
    114      */
    115     public boolean isAttribute()
    116     {
    117         return node.isAttribute();
    118     }
    119
    120     /***
    121      * Returns this node's name.
    122      *
    123      * @return the name
    124      */
    125     public QName getName()
    126     {
    127         return new QName(null, node.getName());
    128     }
    129
    130     /***
    131      * Returns this node's base value. This is the associated configuration
    132      * node.
    133      *
    134      * @return the base value
    135      */
    136     public Object getBaseValue()
    137     {
    138         return node;
    139     }
    140
    141     /***
    142      * Returns the immediate node. This is the associated configuration node.
    143      *
    144      * @return the immediate node
    145      */
    146     public Object getImmediateNode()
    147     {
    148         return node;
    149     }
    150
    151     /***
    152      * Returns the value of this node.
    153      *
    154      * @return the represented node's value
    155      */
    156     public Object getValue()
    157     {
    158         return node.getValue();
    159     }
    160
    161     /***
    162      * Sets the value of this node.
    163      *
    164      * @param value the new value
    165      */
    166     public void setValue(Object value)
    167     {
    168         node.setValue(value);
    169     }
    170
    171     /***
    172      * Compares two child node pointers.
    173      *
    174      * @param pointer1 one pointer
    175      * @param pointer2 another pointer
    176      * @return a flag, which pointer should be sorted first
    177      */
    178     public int compareChildNodePointers(NodePointer pointer1,
    179             NodePointer pointer2)
    180     {
    181         ConfigurationNode node1 = (ConfigurationNode) pointer1.getBaseValue();
    182         ConfigurationNode node2 = (ConfigurationNode) pointer2.getBaseValue();
    183
    184         // attributes will be sorted before child nodes
    185         if (node1.isAttribute() && !node2.isAttribute())
    186         {
    187             return -1;
    188         }
    189         else if (node2.isAttribute() && !node1.isAttribute())
    190         {
    191             return 1;
    192         }
    193
    194         else
    195         {
    196             // sort based on the occurrence in the sub node list
    197             List subNodes = node1.isAttribute() ? node.getAttributes() : node
    198                     .getChildren();
    199             for (Iterator it = subNodes.iterator(); it.hasNext();)
    200             {
    201                 ConfigurationNode child = (ConfigurationNode) it.next();
    202                 if (child == node1)
    203                 {
    204                     return -1;
    205                 }
    206                 else if (child == node2)
    207                 {
    208                     return 1;
    209                 }
    210             }
    211             return 0; // should not happen
    212         }
    213     }
    214
    215     /***
    216      * Returns an iterator for the attributes that match the given name.
    217      *
    218      * @param name the attribute name
    219      * @return the iterator for the attributes
    220      */
    221     public NodeIterator attributeIterator(QName name)
    222     {
    223         return new ConfigurationNodeIteratorAttribute(this, name);
    224     }
    225
    226     /***
    227      * Returns an iterator for the children of this pointer that match the given
    228      * test object.
    229      *
    230      * @param test the test object
    231      * @param reverse the reverse flag
    232      * @param startWith the start value of the iteration
    233      */
    234     public NodeIterator childIterator(NodeTest test, boolean reverse,
    235             NodePointer startWith)
    236     {
    237         return new ConfigurationNodeIteratorChildren(this, test, reverse,
    238                 startWith);
    239     }
    240
    241     /***
    242      * Tests if this node matches the given test. Configuration nodes are text
    243      * nodes, too because they can contain a value.
    244      *
    245      * @param test the test object
    246      * @return a flag if this node corresponds to the test
    247      */
    248     public boolean testNode(NodeTest test)
    249     {
    250         if (test instanceof NodeTypeTest
    251                 && ((NodeTypeTest) test).getNodeType() == Compiler.NODE_TYPE_TEXT)
    252         {
    253             return true;
    254         }
    255         return super.testNode(test);
    256     }
    257 }