1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath.ri.model;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.Vector;
31
32 import org.apache.commons.jxpath.AbstractJXPathTest;
33 import org.apache.commons.jxpath.JXPathContext;
34 import org.apache.commons.jxpath.Pointer;
35 import org.apache.commons.jxpath.TestBean;
36 import org.apache.commons.jxpath.TestMixedModelBean;
37 import org.apache.commons.jxpath.TestNull;
38 import org.apache.commons.jxpath.Variables;
39 import org.junit.jupiter.api.BeforeEach;
40 import org.junit.jupiter.api.Test;
41
42
43
44
45 public class MixedModelTest extends AbstractJXPathTest {
46
47 private JXPathContext context;
48
49 @Override
50 @BeforeEach
51 public void setUp() {
52 final TestMixedModelBean bean = new TestMixedModelBean();
53 context = JXPathContext.newContext(bean);
54 context.setFactory(new TestMixedModelFactory());
55 context.setLocale(Locale.US);
56 final Variables vars = context.getVariables();
57 vars.declareVariable("string", bean.getString());
58 vars.declareVariable("bean", bean.getBean());
59 vars.declareVariable("map", bean.getMap());
60 vars.declareVariable("list", bean.getList());
61 vars.declareVariable("document", bean.getDocument());
62 vars.declareVariable("element", bean.getElement());
63 vars.declareVariable("container", bean.getContainer());
64 vars.declareVariable("testnull", new TestNull());
65 final int[][] matrix = new int[1][];
66 matrix[0] = new int[1];
67 matrix[0][0] = 3;
68 vars.declareVariable("matrix", matrix);
69 }
70
71 @Test
72 public void testBeanBean() {
73 assertXPathValueAndPointer(context, "bean/int", Integer.valueOf(1), "/bean/int");
74 }
75
76 @Test
77 public void testBeanContainer() {
78 assertXPathValueAndPointer(context, "container/vendor/location/address/city", "Fruit Market", "/container/vendor[1]/location[2]/address[1]/city[1]");
79 }
80
81 @Test
82 public void testBeanDocument() {
83 assertXPathValueAndPointer(context, "document/vendor/location/address/city", "Fruit Market", "/document/vendor[1]/location[2]/address[1]/city[1]");
84 }
85
86 @Test
87 public void testBeanElement() {
88 assertXPathValueAndPointer(context, "element/location/address/city", "Fruit Market", "/element/location[2]/address[1]/city[1]");
89 }
90
91 @Test
92 public void testBeanList() {
93 assertXPathValueAndPointer(context, "list[1]", "string", "/list[1]");
94 }
95
96 @Test
97 public void testBeanMap() {
98 assertXPathValueAndPointer(context, "map/string", "string", "/map[@name='string']");
99 }
100
101 @Test
102 public void testBeanPrimitive() {
103 assertXPathValueAndPointer(context, "string", "string", "/string");
104 }
105
106
107
108
109 @Test
110 public void testCollectionPointer() {
111 final List list = new ArrayList();
112 final Map map = new HashMap();
113 map.put("KeyOne", "SomeStringOne");
114 map.put("KeyTwo", "SomeStringTwo");
115 final Map map2 = new HashMap();
116 map2.put("KeyA", "StringA");
117 map2.put("KeyB", "StringB");
118 map.put("KeyThree", map2);
119 list.add(map);
120 final List list2 = new ArrayList();
121 list2.add("foo");
122 list2.add(map);
123 list2.add(map);
124 list.add(list2);
125 context = JXPathContext.newContext(list);
126 assertEquals("SomeStringOne", context.getValue(".[1]/KeyOne"));
127 assertEquals("StringA", context.getValue(".[1]/KeyThree/KeyA"));
128 assertEquals(Integer.valueOf(3), context.getValue("size(.[1]/KeyThree)"));
129 assertEquals(Double.valueOf(6.0), context.getValue("count(.[1]/KeyThree/*)"));
130 assertEquals(Double.valueOf(3.0), context.getValue("count(.[1]/KeyThree/KeyA)"));
131 }
132
133 @Test
134 public void testCreatePath() {
135 context = JXPathContext.newContext(new TestBean());
136 context.setFactory(new TestMixedModelFactory());
137 final TestBean bean = (TestBean) context.getContextBean();
138 bean.setMap(null);
139 assertXPathCreatePath(context, "/map[@name='TestKey5']/nestedBean/int", Integer.valueOf(1), "/map[@name='TestKey5']/nestedBean/int");
140 bean.setMap(null);
141 assertXPathCreatePath(context, "/map[@name='TestKey5']/beans[2]/int", Integer.valueOf(1), "/map[@name='TestKey5']/beans[2]/int");
142 }
143
144 @Test
145 public void testCreatePathAndSetValueWithMatrix() {
146 context.setValue("matrix", null);
147
148
149 assertXPathCreatePathAndSetValue(context, "/matrix[1]/.[1]", Integer.valueOf(4), "/matrix[1]/.[1]");
150 }
151
152 @Test
153 public void testErrorProperty() {
154 context.getVariables().declareVariable("e", new ExceptionPropertyTestBean());
155 assertThrows(Throwable.class, () -> assertXPathValue(context, "$e/errorString", null), "Legitimate exception accessing property");
156 assertXPathPointer(context, "$e/errorString", "$e/errorString");
157 assertXPathPointerLenient(context, "$e/errorStringArray[1]", "$e/errorStringArray[1]");
158 assertXPathPointerIterator(context, "$e/errorString", list("$e/errorString"));
159 assertXPathPointerIterator(context, "$e//error", Collections.EMPTY_LIST);
160 }
161
162
163
164
165 @Test
166 public void testIterateArray() {
167 final Map map = new HashMap();
168 map.put("foo", new String[] { "a", "b", "c" });
169 final JXPathContext context = JXPathContext.newContext(map);
170 assertXPathValueIterator(context, "foo", list("a", "b", "c"));
171 }
172
173 @Test
174 public void testIteratePointersArray() {
175 final Map map = new HashMap();
176 map.put("foo", new String[] { "a", "b", "c" });
177 final JXPathContext context = JXPathContext.newContext(map);
178 final Iterator<Pointer> it = context.iteratePointers("foo");
179 final List<Object> actual = new ArrayList<>();
180 while (it.hasNext()) {
181 final Pointer ptr = it.next();
182 actual.add(context.getValue(ptr.asPath()));
183 }
184 assertEquals(list("a", "b", "c"), actual, "Iterating pointers <" + "foo" + ">");
185 }
186
187 @Test
188 public void testIteratePointersArrayElementWithVariable() {
189 final Map map = new HashMap();
190 map.put("foo", new String[] { "a", "b", "c" });
191 final JXPathContext context = JXPathContext.newContext(map);
192 context.getVariables().declareVariable("x", Integer.valueOf(2));
193 final Iterator<Pointer> it = context.iteratePointers("foo[$x]");
194 final List<Object> actual = new ArrayList<>();
195 while (it.hasNext()) {
196 final Pointer ptr = it.next();
197 actual.add(context.getValue(ptr.asPath()));
198 }
199 assertEquals(list("b"), actual, "Iterating pointers <" + "foo" + ">");
200 }
201
202 @Test
203 public void testIterateVector() {
204 final Map map = new HashMap();
205 final Vector vec = new Vector();
206 vec.add(new HashMap());
207 vec.add(new HashMap());
208 map.put("vec", vec);
209 final JXPathContext context = JXPathContext.newContext(map);
210 assertXPathPointerIterator(context, "/vec", list("/.[@name='vec'][1]", "/.[@name='vec'][2]"));
211 }
212
213 @Test
214 public void testListBean() {
215 assertXPathValueAndPointer(context, "list[2]/int", Integer.valueOf(1), "/list[2]/int");
216 }
217
218 @Test
219 public void testListContainer() {
220 assertXPathValueAndPointer(context, "list[7]/vendor/location/address/city", "Fruit Market", "/list[7]/vendor[1]/location[2]/address[1]/city[1]");
221 }
222
223 @Test
224 public void testListDocument() {
225 assertXPathValueAndPointer(context, "list[5]/vendor/location/address/city", "Fruit Market", "/list[5]/vendor[1]/location[2]/address[1]/city[1]");
226 }
227
228 @Test
229 public void testListElement() {
230 assertXPathValueAndPointer(context, "list[6]/location/address/city", "Fruit Market", "/list[6]/location[2]/address[1]/city[1]");
231 }
232
233 @Test
234 public void testListList() {
235
236
237
238
239
240
241
242
243 assertXPathValueAndPointer(context, "list[4]/.[1]", "string2", "/list[4]/.[1]");
244 }
245
246 @Test
247 public void testListMap() {
248 assertXPathValueAndPointer(context, "list[3]/string", "string", "/list[3][@name='string']");
249 }
250
251 @Test
252 public void testListPrimitive() {
253 assertXPathValueAndPointer(context, "list[1]", "string", "/list[1]");
254 }
255
256 @Test
257 public void testMapBean() {
258 assertXPathValueAndPointer(context, "map/bean/int", Integer.valueOf(1), "/map[@name='bean']/int");
259 }
260
261 @Test
262 public void testMapContainer() {
263 assertXPathValueAndPointer(context, "map/container/vendor/location/address/city", "Fruit Market",
264 "/map[@name='container']" + "/vendor[1]/location[2]/address[1]/city[1]");
265 }
266
267 @Test
268 public void testMapDocument() {
269 assertXPathValueAndPointer(context, "map/document/vendor/location/address/city", "Fruit Market",
270 "/map[@name='document']" + "/vendor[1]/location[2]/address[1]/city[1]");
271 }
272
273 @Test
274 public void testMapElement() {
275 assertXPathValueAndPointer(context, "map/element/location/address/city", "Fruit Market", "/map[@name='element']/location[2]/address[1]/city[1]");
276 }
277
278 @Test
279 public void testMapList() {
280 assertXPathValueAndPointer(context, "map/list[1]", "string", "/map[@name='list'][1]");
281 }
282
283 @Test
284 public void testMapMap() {
285 assertXPathValueAndPointer(context, "map/map/string", "string", "/map[@name='map'][@name='string']");
286 }
287
288 @Test
289 public void testMapPrimitive() {
290 assertXPathValueAndPointer(context, "map/string", "string", "/map[@name='string']");
291 }
292
293 @Test
294 public void testMatrix() {
295 assertXPathValueAndPointer(context, "$matrix[1]/.[1]", Integer.valueOf(3), "$matrix[1]/.[1]");
296 context.setValue("$matrix[1]/.[1]", Integer.valueOf(2));
297 assertXPathValueAndPointer(context, "matrix[1]/.[1]", Integer.valueOf(3), "/matrix[1]/.[1]");
298 context.setValue("matrix[1]/.[1]", "2");
299 assertXPathValue(context, "matrix[1]/.[1]", Integer.valueOf(2));
300 context.getVariables().declareVariable("wholebean", context.getContextBean());
301 assertXPathValueAndPointer(context, "$wholebean/matrix[1]/.[1]", Integer.valueOf(2), "$wholebean/matrix[1]/.[1]");
302 assertThrows(Exception.class, () -> context.setValue("$wholebean/matrix[1]/.[2]", "4"), "Exception setting value of non-existent element");
303 assertThrows(Exception.class, () -> context.setValue("$wholebean/matrix[2]/.[1]", "4"), "Exception setting value of non-existent element");
304 }
305
306 @Test
307 public void testNull() {
308 assertXPathPointerLenient(context, "$null", "$null");
309 assertXPathPointerLenient(context, "$null[3]", "$null[3]");
310 assertXPathPointerLenient(context, "$testnull/nothing", "$testnull/nothing");
311 assertXPathPointerLenient(context, "$testnull/nothing[2]", "$testnull/nothing[2]");
312 assertXPathPointerLenient(context, "beans[8]/int", "/beans[8]/int");
313 assertXPathValueIterator(context, "$testnull/nothing[1]", list(null));
314 final JXPathContext ctx = JXPathContext.newContext(new TestNull());
315 assertXPathValue(ctx, "nothing", null);
316 assertXPathValue(ctx, "child/nothing", null);
317 assertXPathValue(ctx, "array[2]", null);
318 assertXPathValueLenient(ctx, "nothing/something", null);
319 assertXPathValueLenient(ctx, "array[2]/something", null);
320 }
321
322 @Test
323 public void testRootAsCollection() {
324 assertXPathValue(context, ".[1]/string", "string");
325 }
326
327 @Test
328 public void testVar() {
329 context.getVariables().declareVariable("foo:bar", "baz");
330 assertXPathValueAndPointer(context, "$foo:bar", "baz", "$foo:bar");
331 }
332
333 @Test
334 public void testVarBean() {
335 assertXPathValueAndPointer(context, "$bean/int", Integer.valueOf(1), "$bean/int");
336 }
337
338 @Test
339 public void testVarContainer() {
340 assertXPathValueAndPointer(context, "$container/vendor/location/address/city", "Fruit Market", "$container/vendor[1]/location[2]/address[1]/city[1]");
341 }
342
343 @Test
344 public void testVarDocument() {
345 assertXPathValueAndPointer(context, "$document/vendor/location/address/city", "Fruit Market", "$document/vendor[1]/location[2]/address[1]/city[1]");
346 }
347
348 @Test
349 public void testVarElement() {
350 assertXPathValueAndPointer(context, "$element/location/address/city", "Fruit Market", "$element/location[2]/address[1]/city[1]");
351 }
352
353 @Test
354 public void testVarList() {
355 assertXPathValueAndPointer(context, "$list[1]", "string", "$list[1]");
356 }
357
358 @Test
359 public void testVarMap() {
360 assertXPathValueAndPointer(context, "$map/string", "string", "$map[@name='string']");
361 }
362
363 @Test
364 public void testVarPrimitive() {
365 assertXPathValueAndPointer(context, "$string", "string", "$string");
366 }
367 }