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.configuration2.tree;
18  
19  import static org.hamcrest.CoreMatchers.containsString;
20  import static org.hamcrest.MatcherAssert.assertThat;
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertSame;
24  import static org.mockito.Mockito.when;
25  
26  import java.util.Collections;
27  import java.util.LinkedList;
28  import java.util.List;
29  
30  import org.apache.commons.configuration2.ConfigurationAssert;
31  import org.junit.jupiter.api.BeforeAll;
32  import org.junit.jupiter.api.Test;
33  
34  /**
35   * Test class for {@code NodeSelector}.
36   */
37  public class TestNodeSelector {
38      /** Constant for a test key. */
39      private static final String KEY = "tables.testKey";
40  
41      /** The root node for query operations. */
42      private static ImmutableNode root;
43  
44      /** A NodeKeyResolver implementation. */
45      private static NodeKeyResolver<ImmutableNode> resolver;
46  
47      /** The node handler object. */
48      private static NodeHandler<ImmutableNode> handler;
49  
50      /**
51       * Creates a {@code NodeKeyResolver} object to be used in the tests. This resolver object uses a
52       * {@code DefaultExpressionEngine} instance for resolving keys. Methods for obtaining add or update data objects are not
53       * implemented.
54       *
55       * @return the {@code NodeKeyResolver}
56       */
57      private static NodeKeyResolver<ImmutableNode> createResolver() {
58          final NodeKeyResolver<ImmutableNode> resolver = NodeStructureHelper.createResolverMock();
59          NodeStructureHelper.prepareResolveKeyForQueries(resolver);
60          return resolver;
61      }
62  
63      @BeforeAll
64      public static void setUpBeforeClass() throws Exception {
65          resolver = createResolver();
66          handler = new InMemoryNodeModel().getNodeHandler();
67          root = new ImmutableNode.Builder(1).addChild(NodeStructureHelper.ROOT_TABLES_TREE).create();
68      }
69  
70      /**
71       * Tests equals() if the expected result is false.
72       */
73      @Test
74      public void testEqualsFalse() {
75          final NodeSelector selector = new NodeSelector(KEY);
76          NodeSelector sel2 = new NodeSelector("other" + KEY);
77          ConfigurationAssert.checkEquals(selector, sel2, false);
78          sel2 = new NodeSelector(KEY).subSelector(KEY);
79          ConfigurationAssert.checkEquals(selector, sel2, false);
80      }
81  
82      /**
83       * Tests equals() with other objects.
84       */
85      @Test
86      public void testEqualsOtherObjects() {
87          final NodeSelector selector = new NodeSelector(KEY);
88          ConfigurationAssert.checkEquals(selector, null, false);
89          ConfigurationAssert.checkEquals(selector, this, false);
90      }
91  
92      /**
93       * Tests equals() if the expected result is true.
94       */
95      @Test
96      public void testEqualsTrue() {
97          final NodeSelector selector = new NodeSelector(KEY);
98          ConfigurationAssert.checkEquals(selector, selector, true);
99          final NodeSelector sel2 = new NodeSelector(KEY);
100         ConfigurationAssert.checkEquals(selector, sel2, true);
101         final NodeSelector sub1 = selector.subSelector("k2");
102         final NodeSelector sub2 = sel2.subSelector("k2");
103         ConfigurationAssert.checkEquals(sub1, sub2, true);
104     }
105 
106     /**
107      * Tests whether attribute results are ignored when evaluating the key.
108      */
109     @Test
110     public void testSelectIgnoreAttributeResults() {
111         final NodeKeyResolver<ImmutableNode> resolverMock = NodeStructureHelper.createResolverMock();
112         final List<QueryResult<ImmutableNode>> results = new LinkedList<>();
113         results.add(QueryResult.createAttributeResult(NodeStructureHelper.nodeForKey(root, "tables/table(0)"), "type"));
114         final ImmutableNode target = NodeStructureHelper.nodeForKey(root, "tables/table(1)");
115         results.add(QueryResult.createNodeResult(target));
116         results.add(QueryResult.createAttributeResult(NodeStructureHelper.nodeForKey(root, "tables/table(0)/fields/field(1)"), "type"));
117 
118         when(resolverMock.resolveKey(root, KEY, handler)).thenReturn(results);
119 
120         final NodeSelector selector = new NodeSelector(KEY);
121         assertSame(target, selector.select(root, resolverMock, handler));
122     }
123 
124     /**
125      * Tests a select operation with a key yielding multiple target nodes.
126      */
127     @Test
128     public void testSelectMultipleTargets() {
129         final NodeSelector selector = new NodeSelector("tables.table.name");
130         assertNull(selector.select(root, resolver, handler));
131     }
132 
133     /**
134      * Tests a select operation if the key selects an attribute node.
135      */
136     @Test
137     public void testSelectSingleAttributeKey() {
138         final NodeKeyResolver<ImmutableNode> resolverMock = NodeStructureHelper.createResolverMock();
139 
140         when(resolverMock.resolveKey(root, KEY, handler)).thenReturn(Collections.singletonList(QueryResult.createAttributeResult(root, KEY)));
141 
142         final NodeSelector selector = new NodeSelector(KEY);
143         assertNull(selector.select(root, resolverMock, handler));
144     }
145 
146     /**
147      * Tests a successful select operation for a single key.
148      */
149     @Test
150     public void testSelectSingleKeySuccess() {
151         final NodeSelector selector = new NodeSelector("tables.table(0).name");
152         final ImmutableNode target = selector.select(root, resolver, handler);
153         assertEquals("name", target.getNodeName());
154         assertEquals(NodeStructureHelper.table(0), target.getValue());
155     }
156 
157     /**
158      * Tests a select operation with a sub key.
159      */
160     @Test
161     public void testSelectSubKey() {
162         final NodeSelector selectorParent = new NodeSelector("tables.table(0)");
163         final NodeSelector selector = selectorParent.subSelector("fields.field(1).name");
164         final ImmutableNode target = selector.select(root, resolver, handler);
165         assertEquals(NodeStructureHelper.field(0, 1), target.getValue());
166     }
167 
168     /**
169      * Tests a select operation with a sub key which requires complex processing: The first kes produce multiple results;
170      * the final key reduces the result set to a single node.
171      */
172     @Test
173     public void testSelectSubKeyComplexEvaluation() {
174         final NodeSelector first = new NodeSelector("tables.table");
175         final NodeSelector second = first.subSelector("fields");
176         final int fldIdx = NodeStructureHelper.fieldsLength(1) - 1;
177         final NodeSelector selector = second.subSelector("field(" + fldIdx + ").name");
178         final ImmutableNode target = selector.select(root, resolver, handler);
179         assertEquals(NodeStructureHelper.field(1, fldIdx), target.getValue());
180     }
181 
182     /**
183      * Tests a select operation with a sub key which produces multiple results.
184      */
185     @Test
186     public void testSelectSubKeyMultipleResults() {
187         final NodeSelector selectorParent = new NodeSelector("tables.table");
188         final NodeSelector selector = selectorParent.subSelector("fields.field(1).name");
189         assertNull(selector.select(root, resolver, handler));
190     }
191 
192     /**
193      * Tests select() if a key is used which does not yield any results.
194      */
195     @Test
196     public void testSelectSubKeyUnknown() {
197         final NodeSelector selectorParent = new NodeSelector("tables.unknown");
198         final NodeSelector selector = selectorParent.subSelector("fields.field(1).name");
199         assertNull(selector.select(root, resolver, handler));
200     }
201 
202     /**
203      * Tests the string representation.
204      */
205     @Test
206     public void testToString() {
207         final String key2 = "anotherSelectionKey";
208         final NodeSelector selector = new NodeSelector(KEY).subSelector(key2);
209         final String s = selector.toString();
210         assertThat(s, containsString(KEY));
211         assertThat(s, containsString(key2));
212     }
213 }