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    *     https://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.configuration2.tree.xpath;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNull;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  
23  import java.util.List;
24  import java.util.Locale;
25  
26  import org.apache.commons.configuration2.tree.ImmutableNode;
27  import org.apache.commons.configuration2.tree.NodeStructureHelper;
28  import org.apache.commons.jxpath.ri.Compiler;
29  import org.apache.commons.jxpath.ri.QName;
30  import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
31  import org.apache.commons.jxpath.ri.compiler.NodeTest;
32  import org.apache.commons.jxpath.ri.compiler.NodeTypeTest;
33  import org.apache.commons.jxpath.ri.compiler.ProcessingInstructionTest;
34  import org.apache.commons.jxpath.ri.model.NodeIterator;
35  import org.apache.commons.jxpath.ri.model.NodePointer;
36  import org.junit.jupiter.api.BeforeEach;
37  import org.junit.jupiter.api.Test;
38  
39  /**
40   * Test class for ConfigurationNodeIteratorChildren.
41   */
42  public class TestConfigurationNodeIteratorChildren extends AbstractXPathTest {
43      /** Constant for a namespace prefix. */
44      private static final String PREFIX = "commons";
45  
46      /** Constant for the name of a node with a namespace. */
47      private static final String PREFIX_NODE = "configuration";
48  
49      /** Stores the node pointer to the root node. */
50      private ConfigurationNodePointer<ImmutableNode> rootPointer;
51  
52      /**
53       * Helper method for checking the values of the nodes returned by an iterator. Because the values indicate the order of
54       * the child nodes with this test it can be checked whether the nodes were returned in the correct order.
55       *
56       * @param iterator the iterator
57       * @param expectedIndices an array with the expected indices
58       */
59      private void checkValues(final NodeIterator iterator, final int... expectedIndices) {
60          final List<NodePointer> nodes = iterationElements(iterator);
61          for (int i = 0; i < expectedIndices.length; i++) {
62              final ImmutableNode child = (ImmutableNode) nodes.get(i).getImmediateNode();
63              assertTrue(child.getValue().toString().endsWith(String.valueOf(expectedIndices[i])));
64          }
65      }
66  
67      /**
68       * Helper method for creating a node pointer for a given node.
69       *
70       * @param node the node the pointer points to
71       * @return the node pointer
72       */
73      private ConfigurationNodePointer<ImmutableNode> createPointer(final ImmutableNode node) {
74          return new ConfigurationNodePointer<>(node, Locale.getDefault(), handler);
75      }
76  
77      /**
78       * Creates a node pointer to a node which also contains a child node with a namespace prefix.
79       *
80       * @return the node pointer
81       */
82      private ConfigurationNodePointer<ImmutableNode> createPointerWithNamespace() {
83          final ImmutableNode node = new ImmutableNode.Builder(2).addChild(root).addChild(NodeStructureHelper.createNode(PREFIX + ':' + PREFIX_NODE, "test"))
84              .create();
85          return createPointer(node);
86      }
87  
88      @Override
89      @BeforeEach
90      public void setUp() throws Exception {
91          super.setUp();
92          rootPointer = createPointer(root);
93      }
94  
95      /**
96       * Tests to iterate over all children of the root node.
97       */
98      @Test
99      void testIterateAllChildren() {
100         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, null, false, null);
101         assertEquals(CHILD_COUNT, iteratorSize(it));
102         checkValues(it, 1, 2, 3, 4, 5);
103     }
104 
105     /**
106      * Tests a reverse iteration.
107      */
108     @Test
109     void testIterateReverse() {
110         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, null, true, null);
111         assertEquals(CHILD_COUNT, iteratorSize(it));
112         checkValues(it, 5, 4, 3, 2, 1);
113     }
114 
115     /**
116      * Tests defining a start node for the iteration.
117      */
118     @Test
119     void testIterateStartsWith() {
120         final ConfigurationNodePointer<ImmutableNode> childPointer = new ConfigurationNodePointer<>(rootPointer, root.getChildren().get(2), handler);
121         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, null, false, childPointer);
122         assertEquals(0, it.getPosition());
123         final List<NodePointer> nodes = iterationElements(it);
124         assertEquals(CHILD_COUNT - 3, nodes.size());
125         int index = 4;
126         for (final NodePointer np : nodes) {
127             final ImmutableNode node = (ImmutableNode) np.getImmediateNode();
128             assertEquals(String.valueOf(index), node.getValue());
129             index++;
130         }
131     }
132 
133     /**
134      * Tests iteration with an invalid start node. This should cause the iteration to start at the first position.
135      */
136     @Test
137     void testIterateStartsWithInvalid() {
138         final ConfigurationNodePointer<ImmutableNode> childPointer = new ConfigurationNodePointer<>(rootPointer,
139             new ImmutableNode.Builder().name("newNode").create(), handler);
140         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, null, false, childPointer);
141         assertEquals(CHILD_COUNT, iteratorSize(it));
142         it.setPosition(1);
143         final ImmutableNode node = (ImmutableNode) it.getNodePointer().getNode();
144         assertEquals("1", node.getValue());
145     }
146 
147     /**
148      * Tests defining a start node for a reverse iteration.
149      */
150     @Test
151     void testIterateStartsWithReverse() {
152         final ConfigurationNodePointer<ImmutableNode> childPointer = new ConfigurationNodePointer<>(rootPointer, root.getChildren().get(3), handler);
153         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, null, true, childPointer);
154         int value = 3;
155         for (int index = 1; it.setPosition(index); index++, value--) {
156             final ImmutableNode node = (ImmutableNode) it.getNodePointer().getNode();
157             assertEquals(String.valueOf(value), node.getValue(), "Incorrect value at index " + index);
158         }
159         assertEquals(0, value);
160     }
161 
162     /**
163      * Tests whether nodes with a matching namespace prefix can be obtained.
164      */
165     @Test
166     void testIterateWithMatchingPrefixTest() {
167         final NodeNameTest test = new NodeNameTest(new QName(PREFIX, PREFIX_NODE));
168         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(createPointerWithNamespace(), test, false, null);
169         assertEquals(1, iteratorSize(it));
170         for (final NodePointer p : iterationElements(it)) {
171             assertEquals(PREFIX + ':' + PREFIX_NODE, p.getName().getName());
172         }
173     }
174 
175     /**
176      * Tests using a node test that selects a certain sub node name.
177      */
178     @Test
179     void testIterateWithNameTest() {
180         final NodeNameTest test = new NodeNameTest(new QName(null, CHILD_NAME2));
181         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, test, false, null);
182         assertTrue(iteratorSize(it) > 0);
183         for (final NodePointer nd : iterationElements(it)) {
184             assertEquals(CHILD_NAME2, nd.getName().getName());
185         }
186     }
187 
188     /**
189      * Tests using a type test for nodes. This should return all nodes.
190      */
191     @Test
192     void testIterateWithNodeType() {
193         final NodeTypeTest test = new NodeTypeTest(Compiler.NODE_TYPE_NODE);
194         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, test, false, null);
195         assertEquals(CHILD_COUNT, iteratorSize(it));
196     }
197 
198     /**
199      * Tests using a node test that defines a namespace prefix. Because namespaces are not supported, no elements should be
200      * in the iteration.
201      */
202     @Test
203     void testIterateWithPrefixTest() {
204         final NodeNameTest test = new NodeNameTest(new QName("prefix", "*"));
205         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, test, false, null);
206         assertNull(it.getNodePointer());
207         assertEquals(0, iteratorSize(it));
208     }
209 
210     /**
211      * Tests using a not supported test class. This should yield an empty iteration.
212      */
213     @Test
214     void testIterateWithUnknownTest() {
215         final NodeTest test = new ProcessingInstructionTest("test");
216         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, test, false, null);
217         assertEquals(0, iteratorSize(it));
218     }
219 
220     /**
221      * Tests using a type test for a non supported type. This should return an empty iteration.
222      */
223     @Test
224     void testIterateWithUnknownType() {
225         final NodeTypeTest test = new NodeTypeTest(Compiler.NODE_TYPE_COMMENT);
226         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, test, false, null);
227         assertEquals(0, iteratorSize(it));
228     }
229 
230     /**
231      * Tests using a node test with a wildcard name.
232      */
233     @Test
234     void testIterateWithWildcardTest() {
235         final NodeNameTest test = new NodeNameTest(new QName(null, "*"));
236         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(rootPointer, test, false, null);
237         assertEquals(CHILD_COUNT, iteratorSize(it));
238     }
239 
240     /**
241      * Tests whether all nodes with a specific prefix can be obtained.
242      */
243     @Test
244     void testIterateWithWildcardTestPrefix() {
245         final NodeNameTest test = new NodeNameTest(new QName(PREFIX, "*"));
246         final ConfigurationNodeIteratorChildren<ImmutableNode> it = new ConfigurationNodeIteratorChildren<>(createPointerWithNamespace(), test, false, null);
247         assertEquals(1, iteratorSize(it));
248         for (final NodePointer p : iterationElements(it)) {
249             assertEquals(PREFIX + ':' + PREFIX_NODE, p.getName().getName());
250         }
251     }
252 }