1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.configuration2.beanutils;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertFalse;
21 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.Map;
31
32 import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
33 import org.apache.commons.configuration2.HierarchicalConfiguration;
34 import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
35 import org.junit.jupiter.api.Test;
36
37
38
39
40 public class TestXMLBeanDeclaration {
41
42
43
44
45 private static final class XMLBeanDeclarationTestImpl extends XMLBeanDeclaration {
46 public XMLBeanDeclarationTestImpl(final HierarchicalConfiguration<?> config, final NodeData<?> node) {
47 super(config, node);
48 }
49 }
50
51
52 private static final String[] TEST_PROPS = {"firstName", "lastName", "department", "age", "hobby"};
53
54
55 private static final String[] TEST_VALUES = {"John", "Smith", "Engineering", "42", "TV"};
56
57
58 private static final String[] COMPLEX_PROPS = {"address", "car"};
59
60
61 private static final String[] COMPLEX_CLASSES = {"org.apache.commons.configuration.test.AddressTest", "org.apache.commons.configuration.test.CarTest"};
62
63
64 private static final String[][] COMPLEX_ATTRIBUTES = {{"street", "zip", "city", "country"}, {"brand", "color"}};
65
66
67 private static final String[][] COMPLEX_VALUES = {{"Baker Street", "12354", "London", "UK"}, {"Bentley", "silver"}};
68
69
70 private static final String[] CTOR_COMPLEX_ATTRIBUTES = {"secCode", "validTo"};
71
72
73 private static final String[] CTOR_COMPLEX_VALUES = {"20121110181559", "2015-01-31"};
74
75
76 private static final String CTOR_ID = "20121110182006";
77
78
79 private static final String KEY = "myBean";
80
81
82 private static final String VARS = "variables.";
83
84
85
86
87
88
89
90
91 private static void checkProperties(final BeanDeclaration beanDecl, final String[] names, final String[] values) {
92 final Map<String, Object> props = beanDecl.getBeanProperties();
93
94 final Map<String, String> expected = new HashMap<>();
95 for (int i = 0; i < names.length; i++) {
96 expected.put(names[i], values[i]);
97 }
98 assertEquals(expected, props);
99 }
100
101
102
103
104
105
106 private static BaseHierarchicalConfiguration prepareNestedBeanDeclarations() {
107 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
108 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
109 final String keyCtorArg = KEY + ".config-constrarg";
110 setupBeanDeclaration(config, keyCtorArg, CTOR_COMPLEX_ATTRIBUTES, CTOR_COMPLEX_VALUES);
111 config.addProperty(keyCtorArg + "[@config-class]", "TestClass");
112 config.addProperty(keyCtorArg + "(-1)[@config-value]", CTOR_ID);
113 config.addProperty(keyCtorArg + "[@config-type]", "long");
114 for (int i = 0; i < COMPLEX_PROPS.length; i++) {
115 setupBeanDeclaration(config, KEY + '.' + COMPLEX_PROPS[i], COMPLEX_ATTRIBUTES[i], COMPLEX_VALUES[i]);
116 config.addProperty(KEY + '.' + COMPLEX_PROPS[i] + "[@config-class]", COMPLEX_CLASSES[i]);
117 }
118 return config;
119 }
120
121
122
123
124
125
126
127
128
129
130 private static void setupBeanDeclaration(final HierarchicalConfiguration<?> config, final String key, final String[] names, final String[] values) {
131 for (int i = 0; i < names.length; i++) {
132 config.addProperty(key + "[@" + names[i] + "]", values[i]);
133 }
134 }
135
136
137
138
139 @Test
140 void testGetBeanClassName() {
141 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
142 config.addProperty(KEY + "[@config-class]", getClass().getName());
143 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
144 assertEquals(getClass().getName(), decl.getBeanClassName());
145 }
146
147
148
149
150 @Test
151 void testGetBeanClassNameFromDefault() {
152 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
153 config.addProperty(KEY + "[@someProperty]", Boolean.TRUE);
154 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY, false, getClass().getName());
155 assertEquals(getClass().getName(), decl.getBeanClassName());
156 }
157
158
159
160
161 @Test
162 void testGetBeanClassNameUndefined() {
163 final XMLBeanDeclaration decl = new XMLBeanDeclaration(new BaseHierarchicalConfiguration());
164 assertNull(decl.getBeanClassName());
165 }
166
167
168
169
170 @Test
171 void testGetBeanClassNameUndefinedWithEx() {
172 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
173 config.setThrowExceptionOnMissing(true);
174 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
175 assertNull(decl.getBeanClassName());
176 }
177
178
179
180
181 @Test
182 void testGetBeanFactoryName() {
183 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
184 config.addProperty(KEY + "[@config-factory]", "myFactory");
185 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
186 assertEquals("myFactory", decl.getBeanFactoryName());
187 }
188
189
190
191
192 @Test
193 void testGetBeanFactoryNameUndefined() {
194 final XMLBeanDeclaration decl = new XMLBeanDeclaration(new BaseHierarchicalConfiguration());
195 assertNull(decl.getBeanFactoryName());
196 }
197
198
199
200
201 @Test
202 void testGetBeanFactoryNameUndefinedWithEx() {
203 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
204 config.setThrowExceptionOnMissing(true);
205 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
206 assertNull(decl.getBeanFactoryName());
207 }
208
209
210
211
212 @Test
213 void testGetBeanFactoryParameter() {
214 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
215 config.addProperty(KEY + "[@config-factoryParam]", "myFactoryParameter");
216 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
217 assertEquals("myFactoryParameter", decl.getBeanFactoryParameter());
218 }
219
220
221
222
223 @Test
224 void testGetBeanFactoryParameterUndefined() {
225 final XMLBeanDeclaration decl = new XMLBeanDeclaration(new BaseHierarchicalConfiguration());
226 assertNull(decl.getBeanFactoryParameter());
227 }
228
229
230
231
232 @Test
233 void testGetBeanFactoryParameterUndefinedWithEx() {
234 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
235 config.setThrowExceptionOnMissing(true);
236 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
237 assertNull(decl.getBeanFactoryParameter());
238 }
239
240
241
242
243 @Test
244 void testGetBeanProperties() {
245 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
246 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
247 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
248 checkProperties(decl, TEST_PROPS, TEST_VALUES);
249 }
250
251
252
253
254 @Test
255 void testGetBeanPropertiesEmpty() {
256 final XMLBeanDeclaration decl = new XMLBeanDeclaration(new BaseHierarchicalConfiguration());
257 final Map<String, Object> props = decl.getBeanProperties();
258 assertTrue(props == null || props.isEmpty());
259 }
260
261
262
263
264 @Test
265 void testGetBeanPropertiesWithReservedAttributes() {
266 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
267 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
268 config.addProperty(KEY + "[@config-testattr]", "yes");
269 config.addProperty(KEY + "[@config-anothertest]", "this, too");
270 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
271 checkProperties(decl, TEST_PROPS, TEST_VALUES);
272 }
273
274
275
276
277 @Test
278 void testGetConstructorArgs() {
279 final BaseHierarchicalConfiguration config = prepareNestedBeanDeclarations();
280 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
281 final Collection<ConstructorArg> args = decl.getConstructorArgs();
282 assertEquals(2, args.size());
283 final Iterator<ConstructorArg> it = args.iterator();
284 final ConstructorArg arg1 = it.next();
285 assertTrue(arg1.isNestedBeanDeclaration());
286 checkProperties(arg1.getBeanDeclaration(), CTOR_COMPLEX_ATTRIBUTES, CTOR_COMPLEX_VALUES);
287 assertNull(arg1.getTypeName());
288 assertEquals("TestClass", arg1.getBeanDeclaration().getBeanClassName());
289 final ConstructorArg arg2 = it.next();
290 assertFalse(arg2.isNestedBeanDeclaration());
291 assertEquals(CTOR_ID, arg2.getValue());
292 assertEquals("long", arg2.getTypeName());
293 }
294
295
296
297
298 @Test
299 void testGetConstructorArgsNullArg() {
300 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
301 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
302 config.addProperty(KEY + ".config-constrarg", "");
303 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
304 final Collection<ConstructorArg> args = decl.getConstructorArgs();
305 assertEquals(1, args.size());
306 final ConstructorArg arg = args.iterator().next();
307 assertFalse(arg.isNestedBeanDeclaration());
308 assertNull(arg.getValue());
309 }
310
311
312
313
314 @Test
315 void testGetInterpolatedBeanProperties() {
316 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
317 final String[] varValues = new String[TEST_PROPS.length];
318 for (int i = 0; i < TEST_PROPS.length; i++) {
319 varValues[i] = "${" + VARS + TEST_PROPS[i] + "}";
320 config.addProperty(VARS + TEST_PROPS[i], TEST_VALUES[i]);
321 }
322 setupBeanDeclaration(config, KEY, TEST_PROPS, varValues);
323 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
324 checkProperties(decl, TEST_PROPS, TEST_VALUES);
325 }
326
327
328
329
330 @Test
331 void testGetInterpolatedConstructorArgs() {
332 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
333 final String expectedValue = "ctorArg";
334 config.addProperty("value", expectedValue);
335 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
336 config.addProperty(KEY + ".config-constrarg[@config-value]", "${value}");
337 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
338 final Collection<ConstructorArg> args = decl.getConstructorArgs();
339 final ConstructorArg arg = args.iterator().next();
340 assertEquals(expectedValue, arg.getValue());
341 }
342
343
344
345
346 @Test
347 void testGetNestedBeanDeclarations() {
348 final BaseHierarchicalConfiguration config = prepareNestedBeanDeclarations();
349 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
350 checkProperties(decl, TEST_PROPS, TEST_VALUES);
351
352 final Map<String, Object> nested = decl.getNestedBeanDeclarations();
353 assertEquals(COMPLEX_PROPS.length, nested.size());
354 for (int i = 0; i < COMPLEX_PROPS.length; i++) {
355 final XMLBeanDeclaration d = (XMLBeanDeclaration) nested.get(COMPLEX_PROPS[i]);
356 assertNotNull(d, "No declaration found for " + COMPLEX_PROPS[i]);
357 checkProperties(d, COMPLEX_ATTRIBUTES[i], COMPLEX_VALUES[i]);
358 assertEquals(COMPLEX_CLASSES[i], d.getBeanClassName());
359 }
360 }
361
362
363
364
365 @Test
366 void testGetNestedBeanDeclarationsEmpty() {
367 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
368 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
369 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
370 final Map<String, Object> nested = decl.getNestedBeanDeclarations();
371 assertTrue(nested == null || nested.isEmpty());
372 }
373
374
375
376
377 @Test
378 void testGetNestedBeanDeclarationsFactoryMethod() {
379 final BaseHierarchicalConfiguration config = prepareNestedBeanDeclarations();
380 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY) {
381 @Override
382 BeanDeclaration createBeanDeclaration(final NodeData<?> node) {
383 return new XMLBeanDeclarationTestImpl(getConfiguration().configurationAt(node.nodeName()), node);
384 }
385 };
386 final Map<String, Object> nested = decl.getNestedBeanDeclarations();
387 for (final String element : COMPLEX_PROPS) {
388 final Object d = nested.get(element);
389 assertInstanceOf(XMLBeanDeclarationTestImpl.class, d, "Wrong class for bean declaration: " + d);
390 }
391 }
392
393
394
395
396
397 @Test
398 void testGetNestedBeanDeclarationsReservedCharacter() {
399 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
400 final String key = KEY + ".address..private";
401 setupBeanDeclaration(config, key, COMPLEX_ATTRIBUTES[0], COMPLEX_VALUES[0]);
402 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
403
404 final Map<String, Object> nested = decl.getNestedBeanDeclarations();
405 assertTrue(nested.containsKey("address.private"));
406 }
407
408
409
410
411
412 @Test
413 void testInitFromMultiValueKey() {
414 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
415 config.addProperty(KEY, "myFirstKey");
416 config.addProperty(KEY, "mySecondKey");
417 assertThrows(ConfigurationRuntimeException.class, () -> new XMLBeanDeclaration(config, KEY));
418 }
419
420
421
422
423 @Test
424 void testInitFromNullConfiguration() {
425 assertThrows(IllegalArgumentException.class, () -> new XMLBeanDeclaration(null));
426 }
427
428
429
430
431 @Test
432 void testInitFromNullConfigurationAndKey() {
433 assertThrows(IllegalArgumentException.class, () -> new XMLBeanDeclaration(null, KEY));
434 }
435
436
437
438
439 @Test
440 void testInitFromUndefinedKey() {
441 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
442 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
443 assertThrows(ConfigurationRuntimeException.class, () -> new XMLBeanDeclaration(config, "undefined_key"));
444 }
445
446
447
448
449
450 @Test
451 void testInitFromUndefinedKeyOptional() {
452 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
453 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
454 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, "undefined_key", true);
455 assertNull(decl.getBeanClassName());
456 }
457
458
459
460
461 @Test
462 void testInterpolateNoInterpolator() {
463 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
464 config.addProperty("value", "expectedValue");
465 setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
466 final String value = "${value}";
467 config.addProperty(KEY + ".config-constrarg[@config-value]", value);
468 config.setInterpolator(null);
469 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY);
470 final Collection<ConstructorArg> args = decl.getConstructorArgs();
471 final ConstructorArg arg = args.iterator().next();
472 assertEquals(value, arg.getValue());
473 }
474
475
476
477
478 @Test
479 public void tetGetBeanClassNameDefaultOverride() {
480 final BaseHierarchicalConfiguration config = new BaseHierarchicalConfiguration();
481 config.addProperty(KEY + "[@config-class]", getClass().getName());
482 final XMLBeanDeclaration decl = new XMLBeanDeclaration(config, KEY, false, "someDefaultClassName");
483 assertEquals(getClass().getName(), decl.getBeanClassName());
484 }
485 }