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