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