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.ArrayList;
20  import java.util.Collections;
21  import java.util.List;
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.NodeNameTest;
27  import org.apache.commons.jxpath.ri.compiler.NodeTest;
28  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
29  import org.apache.commons.jxpath.ri.model.NodePointer;
30  import org.apache.commons.lang.StringUtils;
31  
32  /**
33   * A specialized iterator implementation for the child nodes of a configuration
34   * node.
35   *
36   * @since 1.3
37   * @author <a
38   * href="http://commons.apache.org/configuration/team-list.html">Commons
39   * Configuration team</a>
40   * @version $Id: ConfigurationNodeIteratorChildren.java 1206493 2011-11-26 16:56:42Z oheger $
41   */
42  class ConfigurationNodeIteratorChildren extends ConfigurationNodeIteratorBase
43  {
44      /**
45       * Creates a new instance of {@code ConfigurationNodeIteratorChildren}
46       * and initializes it.
47       *
48       * @param parent the parent pointer
49       * @param nodeTest the test selecting the sub nodes
50       * @param reverse the reverse flag
51       * @param startsWith the first element of the iteration
52       */
53      public ConfigurationNodeIteratorChildren(NodePointer parent,
54              NodeTest nodeTest, boolean reverse, NodePointer startsWith)
55      {
56          super(parent, reverse);
57          ConfigurationNode root = (ConfigurationNode) parent.getNode();
58          List<ConfigurationNode> childNodes = createSubNodeList(root, nodeTest);
59          initSubNodeList(childNodes);
60          if (startsWith != null)
61          {
62              setStartOffset(findStartIndex(root,
63                      (ConfigurationNode) startsWith.getNode()));
64          }
65      }
66  
67      /**
68       * Creates the list with sub nodes. This method gets called during
69       * initialization phase. It finds out, based on the given test, which nodes
70       * must be iterated over.
71       *
72       * @param node the current node
73       * @param test the test object
74       * @return a list with the matching nodes
75       */
76      protected List<ConfigurationNode> createSubNodeList(ConfigurationNode node, NodeTest test)
77      {
78          List<ConfigurationNode> children = node.getChildren();
79  
80          if (test == null)
81          {
82              return children;
83          }
84          else
85          {
86              if (test instanceof NodeNameTest)
87              {
88                  NodeNameTest nameTest = (NodeNameTest) test;
89                  QName name = nameTest.getNodeName();
90                  if (name.getPrefix() == null)
91                  {
92                      if (nameTest.isWildcard())
93                      {
94                          return children;
95                      }
96  
97                      List<ConfigurationNode> result = new ArrayList<ConfigurationNode>();
98                      for (ConfigurationNode child : children)
99                      {
100                         if (StringUtils.equals(name.getName(), child.getName()))
101                         {
102                             result.add(child);
103                         }
104                     }
105                     return result;
106                 }
107             }
108 
109             else if (test instanceof NodeTypeTest)
110             {
111                 NodeTypeTest typeTest = (NodeTypeTest) test;
112                 if (typeTest.getNodeType() == Compiler.NODE_TYPE_NODE
113                         || typeTest.getNodeType() == Compiler.NODE_TYPE_TEXT)
114                 {
115                     return children;
116                 }
117             }
118         }
119 
120         return Collections.emptyList();
121     }
122 
123     /**
124      * Determines the start position of the iteration. Finds the index of the
125      * given start node in the children of the root node.
126      *
127      * @param node the root node
128      * @param startNode the start node
129      * @return the start node's index
130      */
131     protected int findStartIndex(ConfigurationNode node,
132             ConfigurationNode startNode)
133     {
134         for (int index = 0; index < node.getChildrenCount(); index++)
135         {
136             if (node.getChild(index) == startNode)
137             {
138                 return index;
139             }
140         }
141 
142         return -1;
143     }
144 }