1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration2.tree;
18
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.when;
22
23 import java.util.NoSuchElementException;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26
27 import org.apache.commons.lang3.StringUtils;
28
29
30
31
32
33 public class NodeStructureHelper {
34
35 private static final Pattern PAT_KEY_WITH_INDEX = Pattern.compile("(\\w+)\\((\\d+)\\)");
36
37
38 private static final String PATH_SEPARATOR = "/";
39
40
41 private static final String[] AUTHORS = {"Shakespeare", "Homer", "Simmons"};
42
43
44 private static final String[][] WORKS = {{"Troilus and Cressida", "The Tempest", "A Midsummer Night's Dream"}, {"Ilias"}, {"Ilium", "Hyperion"}};
45
46
47 private static final String[][][] PERSONAE = {{
48
49 {"Troilus", "Cressidia", "Ajax", "Achilles"}, {"Prospero", "Ariel"}, {"Oberon", "Titania", "Puck"}},
50 {
51
52 {"Achilles", "Agamemnon", "Hektor"}},
53 {
54
55 {"Hockenberry", "Achilles"}, {"Shrike", "Moneta", "Consul", "Weintraub"}}};
56
57
58 private static final String[] TABLES = {"users", "documents"};
59
60
61
62
63 private static final String[][] FIELDS = {{"uid", "uname", "firstName", "lastName", "email"},
64 {"docid", "name", "creationDate", "authorID", "version", "length"}};
65
66
67 public static final String ATTR_AUTHOR = "author";
68
69
70 public static final String ELEM_ORG_VALUE = "originalValue";
71
72
73 public static final String ATTR_TESTED = "tested";
74
75
76 public static final ImmutableNode ROOT_AUTHORS_TREE = createAuthorsTree();
77
78
79 public static final ImmutableNode ROOT_PERSONAE_TREE = createPersonaeTree();
80
81
82 public static final ImmutableNode ROOT_TABLES_TREE = createTablesTree();
83
84
85
86
87
88
89
90
91 public static String appendPath(final String path, final String component) {
92 final StringBuilder buf = new StringBuilder(StringUtils.length(path) + StringUtils.length(component) + 1);
93 buf.append(path).append(PATH_SEPARATOR).append(component);
94 return buf.toString();
95 }
96
97
98
99
100
101
102
103 public static String author(final int idx) {
104 return AUTHORS[idx];
105 }
106
107
108
109
110
111
112 public static int authorsLength() {
113 return AUTHORS.length;
114 }
115
116
117
118
119
120
121
122 private static ImmutableNode createAuthorsTree() {
123 final ImmutableNode.Builder rootBuilder = new ImmutableNode.Builder(AUTHORS.length);
124 for (int author = 0; author < AUTHORS.length; author++) {
125 final ImmutableNode.Builder authorBuilder = new ImmutableNode.Builder();
126 authorBuilder.name(AUTHORS[author]);
127 for (int work = 0; work < WORKS[author].length; work++) {
128 final ImmutableNode.Builder workBuilder = new ImmutableNode.Builder();
129 workBuilder.name(WORKS[author][work]);
130 for (final String person : PERSONAE[author][work]) {
131 workBuilder.addChild(new ImmutableNode.Builder().name(person).create());
132 }
133 authorBuilder.addChild(workBuilder.create());
134 }
135 rootBuilder.addChild(authorBuilder.create());
136 }
137 return rootBuilder.name("authorTree").create();
138 }
139
140
141
142
143
144
145
146
147 public static ImmutableNode createFieldNode(final String name) {
148 final ImmutableNode.Builder fldBuilder = new ImmutableNode.Builder(1);
149 fldBuilder.addChild(createNode("name", name));
150 return fldBuilder.name("field").create();
151 }
152
153
154
155
156
157
158
159
160 public static ImmutableNode createNode(final String name, final Object value) {
161 return new ImmutableNode.Builder().name(name).value(value).create();
162 }
163
164
165
166
167
168
169
170
171 private static ImmutableNode createPersonaeTree() {
172 final ImmutableNode.Builder rootBuilder = new ImmutableNode.Builder();
173 for (int author = 0; author < AUTHORS.length; author++) {
174 for (int work = 0; work < WORKS[author].length; work++) {
175 for (final String person : PERSONAE[author][work]) {
176 final ImmutableNode orgValue = new ImmutableNode.Builder().name(ELEM_ORG_VALUE).value("yes").addAttribute(ATTR_TESTED, Boolean.FALSE)
177 .create();
178 final ImmutableNode workNode = new ImmutableNode.Builder(1).name(WORKS[author][work]).addChild(orgValue).create();
179 final ImmutableNode personNode = new ImmutableNode.Builder(1).name(person).addAttribute(ATTR_AUTHOR, AUTHORS[author]).addChild(workNode)
180 .create();
181 rootBuilder.addChild(personNode);
182 }
183 }
184 }
185 return rootBuilder.create();
186 }
187
188
189
190
191
192
193 @SuppressWarnings("unchecked")
194 public static NodeKeyResolver<ImmutableNode> createResolverMock() {
195 return mock(NodeKeyResolver.class);
196 }
197
198
199
200
201
202
203
204
205 private static ImmutableNode createTablesTree() {
206 return createTablesTree(TABLES, FIELDS);
207 }
208
209
210
211
212
213
214
215
216
217 public static ImmutableNode createTablesTree(final String[] tables, final String[][] fields) {
218 final ImmutableNode.Builder bldTables = new ImmutableNode.Builder(tables.length);
219 bldTables.name("tables");
220 for (int i = 0; i < tables.length; i++) {
221 final ImmutableNode.Builder bldTable = new ImmutableNode.Builder(2);
222 bldTable.addChild(createNode("name", tables[i]));
223 final ImmutableNode.Builder bldFields = new ImmutableNode.Builder(fields[i].length);
224 bldFields.name("fields");
225
226 for (int j = 0; j < fields[i].length; j++) {
227 bldFields.addChild(createFieldNode(fields[i][j]));
228 }
229 bldTable.addChild(bldFields.create());
230 bldTables.addChild(bldTable.name("table").create());
231 }
232 return bldTables.create();
233 }
234
235
236
237
238
239
240 public static void prepareResolveAddKeys(final NodeKeyResolver<ImmutableNode> resolver) {
241 when(resolver.resolveAddKey(any(), any(), any())).then(invocation -> {
242 final ImmutableNode root = invocation.getArgument(0, ImmutableNode.class);
243 final String key = invocation.getArgument(1, String.class);
244 final TreeData handler = invocation.getArgument(2, TreeData.class);
245 return DefaultExpressionEngine.INSTANCE.prepareAdd(root, key, handler);
246 });
247 }
248
249
250
251
252
253
254
255 @SuppressWarnings("unchecked")
256 public static void prepareResolveKeyForQueries(final NodeKeyResolver<ImmutableNode> resolver) {
257 when(resolver.resolveKey(any(), any(), any())).thenAnswer(invocation -> {
258 final ImmutableNode root = invocation.getArgument(0, ImmutableNode.class);
259 final String key = invocation.getArgument(1, String.class);
260 final NodeHandler<ImmutableNode> handler = invocation.getArgument(2, NodeHandler.class);
261 return DefaultExpressionEngine.INSTANCE.query(root, key, handler);
262 });
263 }
264
265
266
267
268
269
270
271
272 public static String field(final int tabIdx, final int fldIdx) {
273 return FIELDS[tabIdx][fldIdx];
274 }
275
276
277
278
279
280
281
282 public static int fieldsLength(final int tabIdx) {
283 return FIELDS[tabIdx].length;
284 }
285
286
287
288
289
290
291
292
293
294
295 private static ImmutableNode findNode(final ImmutableNode parent, final String[] components, final int currentIdx) {
296 if (currentIdx >= components.length) {
297 return parent;
298 }
299
300 final Matcher m = PAT_KEY_WITH_INDEX.matcher(components[currentIdx]);
301 final String childName;
302 final int childIndex;
303 if (m.matches()) {
304 childName = m.group(1);
305 childIndex = Integer.parseInt(m.group(2));
306 } else {
307 childName = components[currentIdx];
308 childIndex = 0;
309 }
310
311 int foundIdx = 0;
312 for (final ImmutableNode node : parent) {
313 if (childName.equals(node.getNodeName()) && foundIdx++ == childIndex) {
314 return findNode(node, components, currentIdx + 1);
315 }
316 }
317 throw new NoSuchElementException("Cannot resolve child " + components[currentIdx]);
318 }
319
320
321
322
323
324
325
326 public static String[][] getClonedFields() {
327 final String[][] fieldNamesNew = new String[FIELDS.length][];
328 for (int i = 0; i < FIELDS.length; i++) {
329 fieldNamesNew[i] = FIELDS[i].clone();
330 }
331 return fieldNamesNew;
332 }
333
334
335
336
337
338
339
340 public static String[] getClonedTables() {
341 return TABLES.clone();
342 }
343
344
345
346
347
348
349
350
351
352
353
354 public static ImmutableNode nodeForKey(final ImmutableNode root, final String key) {
355 final String[] components = key.split(PATH_SEPARATOR);
356 return findNode(root, components, 0);
357 }
358
359
360
361
362
363
364
365
366
367
368 public static ImmutableNode nodeForKey(final InMemoryNodeModel model, final String key) {
369 return nodeForKey(model.getRootNode(), key);
370 }
371
372
373
374
375
376
377
378
379
380
381
382 public static ImmutableNode nodeForKey(final NodeHandler<ImmutableNode> handler, final String key) {
383 return nodeForKey(handler.getRootNode(), key);
384 }
385
386
387
388
389
390
391
392 public static String nodePath(final String... path) {
393 return StringUtils.join(path, PATH_SEPARATOR);
394 }
395
396
397
398
399
400
401
402
403 public static String nodePathWithEndNode(final String endNode, final String... path) {
404 return nodePath(path) + PATH_SEPARATOR + endNode;
405 }
406
407
408
409
410
411
412
413
414
415 public static String persona(final int authorIdx, final int workIdx, final int personaIdx) {
416 return PERSONAE[authorIdx][workIdx][personaIdx];
417 }
418
419
420
421
422
423
424
425
426 public static int personaeLength(final int authorIdx, final int workIdx) {
427 return PERSONAE[authorIdx][workIdx].length;
428 }
429
430
431
432
433
434
435
436 public static String table(final int idx) {
437 return TABLES[idx];
438 }
439
440
441
442
443
444
445 public static int tablesLength() {
446 return TABLES.length;
447 }
448
449
450
451
452
453
454
455
456 public static String work(final int authorIdx, final int idx) {
457 return WORKS[authorIdx][idx];
458 }
459
460
461
462
463
464
465
466 public static int worksLength(final int authorIdx) {
467 return WORKS[authorIdx].length;
468 }
469 }