1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri.model;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Locale;
24
25 import org.apache.commons.jxpath.AbstractFactory;
26 import org.apache.commons.jxpath.ClassFunctions;
27 import org.apache.commons.jxpath.JXPathContext;
28 import org.apache.commons.jxpath.JXPathTestCase;
29 import org.apache.commons.jxpath.NestedTestBean;
30 import org.apache.commons.jxpath.Pointer;
31 import org.apache.commons.jxpath.ri.QName;
32 import org.apache.commons.jxpath.ri.compiler.NodeNameTest;
33 import org.apache.commons.jxpath.ri.compiler.TestFunctions;
34 import org.apache.commons.jxpath.ri.model.beans.PropertyOwnerPointer;
35 import org.apache.commons.jxpath.ri.model.beans.PropertyPointer;
36 import org.apache.commons.jxpath.ri.model.dynabeans.DynaBeanModelTest;
37
38
39
40
41
42
43
44 public abstract class BeanModelTestCase extends JXPathTestCase {
45 private JXPathContext context;
46
47 public void setUp() {
48
49 context = JXPathContext.newContext(createContextBean());
50 context.setLocale(Locale.US);
51 context.setFactory(getAbstractFactory());
52
53 }
54
55 protected abstract Object createContextBean();
56 protected abstract AbstractFactory getAbstractFactory();
57
58
59
60
61 public void testIndividualIterators() {
62 testIndividual(+1, 0, true, false, 0);
63 testIndividual(-1, 0, true, false, 4);
64
65 testIndividual(0, -1, true, true, 4);
66 testIndividual(+1, -1, true, true, 4);
67 testIndividual(-1, -1, true, true, 0);
68
69 testIndividual(0, 1, true, false, 2);
70 testIndividual(0, 1, true, true, 1);
71
72 testIndividual(0, 0, false, false, 4);
73 testIndividual(0, 0, false, true, 4);
74 }
75
76 private void testIndividual(
77 int relativePropertyIndex,
78 int offset,
79 boolean useStartLocation,
80 boolean reverse,
81 int expected)
82 {
83 PropertyOwnerPointer root =
84 (PropertyOwnerPointer) NodePointer.newNodePointer(
85 new QName(null, "root"),
86 createContextBean(),
87 Locale.getDefault());
88
89 NodeIterator it;
90
91 PropertyPointer start = null;
92
93 if (useStartLocation) {
94 start = root.getPropertyPointer();
95 start.setPropertyIndex(
96 relativeProperty(start, relativePropertyIndex));
97 start.setIndex(offset);
98 }
99 it =
100 root.childIterator(
101 new NodeNameTest(new QName(null, "integers")),
102 reverse,
103 start);
104
105 int size = 0;
106 while (it.setPosition(it.getPosition() + 1)) {
107 size++;
108 }
109 assertEquals(
110 "ITERATIONS: Individual, relativePropertyIndex="
111 + relativePropertyIndex
112 + ", offset="
113 + offset
114 + ", useStartLocation="
115 + useStartLocation
116 + ", reverse="
117 + reverse,
118 expected,
119 size);
120 }
121
122
123
124
125 public void testMultipleIterators() {
126 testMultiple(0, 0, true, false, 20);
127
128 testMultiple(3, 0, true, false, 16);
129 testMultiple(3, -1, true, true, 8);
130 testMultiple(3, 0, true, true, 4);
131 testMultiple(0, 0, false, false, 21);
132 testMultiple(0, 0, false, true, 21);
133
134 testMultiple(3, 1, true, false, 15);
135 testMultiple(3, 3, true, false, 13);
136 }
137
138 private void testMultiple(
139 int propertyIndex,
140 int offset,
141 boolean useStartLocation,
142 boolean reverse,
143 int expected)
144 {
145 PropertyOwnerPointer root =
146 (PropertyOwnerPointer) NodePointer.newNodePointer(
147 new QName(null, "root"),
148 createContextBean(),
149 Locale.getDefault());
150 NodeIterator it;
151
152 PropertyPointer start = null;
153
154 if (useStartLocation) {
155 start = root.getPropertyPointer();
156 start.setPropertyIndex(propertyIndex);
157 start.setIndex(offset);
158 }
159 it = root.childIterator(null, reverse, start);
160
161 int size = 0;
162 while (it.setPosition(it.getPosition() + 1)) {
163
164 size++;
165 }
166 assertEquals(
167 "ITERATIONS: Multiple, propertyIndex="
168 + propertyIndex
169 + ", offset="
170 + offset
171 + ", useStartLocation="
172 + useStartLocation
173 + ", reverse="
174 + reverse,
175 expected,
176 size);
177 }
178
179 private int relativeProperty(PropertyPointer holder, int offset) {
180 String[] names = holder.getPropertyNames();
181 for (int i = 0; i < names.length; i++) {
182 if (names[i].equals("integers")) {
183 return i + offset;
184 }
185 }
186 return -1;
187 }
188
189 public void testIteratePropertyArrayWithHasNext() {
190 JXPathContext context = JXPathContext.newContext(createContextBean());
191 Iterator it = context.iteratePointers("/integers");
192 List actual = new ArrayList();
193 while (it.hasNext()) {
194 actual.add(((Pointer) it.next()).asPath());
195 }
196 assertEquals(
197 "Iterating 'hasNext'/'next'<" + "/integers" + ">",
198 list(
199 "/integers[1]",
200 "/integers[2]",
201 "/integers[3]",
202 "/integers[4]"),
203 actual);
204 }
205
206 public void testIteratePropertyArrayWithoutHasNext() {
207 JXPathContext context = JXPathContext.newContext(createContextBean());
208 Iterator it = context.iteratePointers("/integers");
209 List actual = new ArrayList();
210 for (int i = 0; i < 4; i++) {
211 actual.add(it.next().toString());
212 }
213 assertEquals(
214 "Iterating 'next'<" + "/integers" + ">",
215 list(
216 "/integers[1]",
217 "/integers[2]",
218 "/integers[3]",
219 "/integers[4]"),
220 actual);
221 }
222
223 public void testIterateAndSet() {
224 JXPathContext context = JXPathContext.newContext(createContextBean());
225
226 Iterator it = context.iteratePointers("beans/int");
227 int i = 5;
228 while (it.hasNext()) {
229 NodePointer pointer = (NodePointer) it.next();
230 pointer.setValue(new Integer(i++));
231 }
232
233 it = context.iteratePointers("beans/int");
234 List actual = new ArrayList();
235 while (it.hasNext()) {
236 actual.add(((Pointer) it.next()).getValue());
237 }
238 assertEquals(
239 "Iterating <" + "beans/int" + ">",
240 list(new Integer(5), new Integer(6)),
241 actual);
242 }
243
244
245
246
247 public void testIteratePointerSetValue() {
248 JXPathContext context = JXPathContext.newContext(createContextBean());
249
250 assertXPathValue(context, "/beans[1]/name", "Name 1");
251 assertXPathValue(context, "/beans[2]/name", "Name 2");
252
253
254 context.setValue("/beans[2]/name", "Name 2 set");
255 assertXPathValue(context, "/beans[2]/name", "Name 2 set");
256
257
258 context.setValue("/beans[2]/name", "Name 2");
259 assertXPathValue(context, "/beans[2]/name", "Name 2");
260
261 int iterCount = 0;
262 Iterator iter = context.iteratePointers("/beans/name");
263 while (iter.hasNext()) {
264 iterCount++;
265 Pointer pointer = (Pointer) iter.next();
266 String s = (String) pointer.getValue();
267 s = s + "suffix";
268 pointer.setValue(s);
269 assertEquals("pointer.getValue", s, pointer.getValue());
270
271 assertEquals(
272 "context.getValue",
273 s,
274 context.getValue(pointer.asPath()));
275 }
276 assertEquals("Iteration count", 2, iterCount);
277
278 assertXPathValue(context, "/beans[1]/name", "Name 1suffix");
279 assertXPathValue(context, "/beans[2]/name", "Name 2suffix");
280 }
281
282 public void testRoot() {
283 assertXPathValueAndPointer(context, "/", context.getContextBean(), "/");
284 }
285
286 public void testAxisAncestor() {
287
288 assertXPathValue(context, "int/ancestor::root = /", Boolean.TRUE);
289
290 assertXPathValue(
291 context,
292 "count(beans/name/ancestor-or-self::node())",
293 new Double(5));
294
295 assertXPathValue(
296 context,
297 "beans/name/ancestor-or-self::node()[3] = /",
298 Boolean.TRUE);
299 }
300
301 public void testAxisChild() {
302 assertXPathValue(context, "boolean", Boolean.FALSE);
303
304 assertXPathPointer(context, "boolean", "/boolean");
305
306 assertXPathPointerIterator(context, "boolean", list("/boolean"));
307
308
309 assertXPathValue(context, "count(set)", new Double(3));
310
311
312
313
314 assertXPathValueIterator(context, "foo:boolean", list());
315
316
317 assertXPathValue(context, "count(*)", new Double(21));
318
319
320 assertXPathValue(context, "count(child::node())", new Double(21));
321 }
322
323 public void testAxisChildNestedBean() {
324
325 assertXPathValue(context, "nestedBean/name", "Name 0");
326
327 assertXPathPointer(context, "nestedBean/name", "/nestedBean/name");
328
329 assertXPathPointerIterator(
330 context,
331 "nestedBean/name",
332 list("/nestedBean/name"));
333 }
334
335 public void testAxisChildNestedCollection() {
336 assertXPathValueIterator(
337 context,
338 "integers",
339 list(
340 new Integer(1),
341 new Integer(2),
342 new Integer(3),
343 new Integer(4)));
344
345 assertXPathPointer(context, "integers", "/integers");
346
347 assertXPathPointerIterator(
348 context,
349 "integers",
350 list(
351 "/integers[1]",
352 "/integers[2]",
353 "/integers[3]",
354 "/integers[4]"));
355 }
356
357 public void testIndexPredicate() {
358 assertXPathValue(context, "integers[2]", new Integer(2));
359
360 assertXPathPointer(context, "integers[2]", "/integers[2]");
361
362 assertXPathPointerIterator(
363 context,
364 "integers[2]",
365 list("/integers[2]"));
366
367 assertXPathValue(context, "beans[1]/name", "Name 1");
368
369 assertXPathPointer(context, "beans[1]/name", "/beans[1]/name");
370
371 assertXPathValueIterator(
372 context,
373 "beans[1]/strings",
374 list("String 1", "String 2", "String 3"));
375
376 assertXPathValueIterator(
377 context,
378 "beans/strings[2]",
379 list("String 2", "String 2"));
380
381
382 assertXPathValue(context, "beans/strings[2]", "String 2");
383
384
385 assertXPathValue(context, "(beans/strings[2])[1]", "String 2");
386 }
387
388 public void testAxisDescendant() {
389
390 assertXPathValue(context, "count(descendant::node())", new Double(65));
391
392
393 assertXPathValue(context, "count(descendant::root)", new Double(0));
394
395 assertXPathValue(context, "count(descendant::name)", new Double(7));
396 }
397
398 public void testAxisDescendantOrSelf() {
399
400 assertXPathValueIterator(
401 context,
402 "descendant-or-self::name",
403 set(
404 "Name 1",
405 "Name 2",
406 "Name 3",
407 "Name 6",
408 "Name 0",
409 "Name 5",
410 "Name 4"));
411
412
413 assertXPathValueIterator(
414 context,
415 "//name",
416 set(
417 "Name 1",
418 "Name 2",
419 "Name 3",
420 "Name 6",
421 "Name 0",
422 "Name 5",
423 "Name 4"));
424
425
426 assertXPathValue(
427 context,
428 "count(descendant-or-self::root)",
429 new Double(1));
430
431
432 assertXPathValue(context, "count(nestedBean//.)", new Double(7));
433
434
435 assertXPathValue(context, "count(//self::beans)", new Double(2));
436
437
438 assertXPathValue(
439 context,
440 "count(descendant-or-self::node())",
441 new Double(66));
442
443 }
444
445 public void testAxisFollowing() {
446
447 assertXPathValue(
448 context,
449 "count(nestedBean/strings[2]/following::node())",
450 new Double(21));
451
452 assertXPathValue(
453 context,
454 "count(nestedBean/strings[2]/following::strings)",
455 new Double(7));
456 }
457
458 public void testAxisFollowingSibling() {
459
460 assertXPathValue(
461 context,
462 "count(/nestedBean/following-sibling::node())",
463 new Double(8));
464
465 assertXPathValue(
466 context,
467 "count(/nestedBean/following-sibling::object)",
468 new Double(1));
469
470
471 assertXPathValue(
472 context,
473 "count(/nestedBean/boolean/../following-sibling::node())",
474 new Double(8));
475
476 assertXPathValue(
477 context,
478 "count(/nestedBean/boolean/../following-sibling::object)",
479 new Double(1));
480
481
482 assertXPathValue(
483 context,
484 "count(/descendant::boolean/following-sibling::node())",
485 new Double(53));
486
487 assertXPathValue(
488 context,
489 "count(/descendant::boolean/following-sibling::name)",
490 new Double(7));
491 }
492
493 public void testAxisParent() {
494
495 assertXPathValue(context, "count(/beans/..)", new Double(1));
496
497 assertXPathValue(context, "count(//..)", new Double(9));
498
499 assertXPathValue(context, "count(//../..)", new Double(2));
500
501 assertXPathValueIterator(
502 context,
503 "//parent::beans/name",
504 list("Name 1", "Name 2"));
505 }
506
507 public void testAxisPreceding() {
508
509 assertXPathValue(
510 context,
511 "count(beans[2]/int/preceding::node())",
512 new Double(8));
513
514 assertXPathValue(
515 context,
516 "count(beans[2]/int/preceding::boolean)",
517 new Double(2));
518 }
519
520 public void testAxisPrecedingSibling() {
521
522 assertXPathValue(
523 context,
524 "count(/boolean/preceding-sibling::node())",
525 new Double(2));
526
527 assertXPathValue(
528 context,
529 "count(/nestedBean/int/../preceding-sibling::node())",
530 new Double(12));
531
532 assertXPathValue(
533 context,
534 "count(/descendant::int/preceding-sibling::node())",
535 new Double(10));
536 }
537
538 public void testAxisSelf() {
539
540 assertXPathValue(context, "self::node() = /", Boolean.TRUE);
541
542 assertXPathValue(context, "self::root = /", Boolean.TRUE);
543 }
544
545 public void testUnion() {
546
547 assertXPathValueIterator(
548 context,
549 "integers | beans[1]/strings",
550 list(
551 "String 1",
552 "String 2",
553 "String 3",
554 new Integer(1),
555 new Integer(2),
556 new Integer(3),
557 new Integer(4)));
558
559 assertXPathValue(
560 context,
561 "count((integers | beans[1]/strings)[contains(., '1')])",
562 new Double(2));
563
564 assertXPathValue(
565 context,
566 "count((integers | beans[1]/strings)[name(.) = 'strings'])",
567 new Double(3));
568
569
570
571 assertXPathValue(context, "(integers)[2]", new Integer(2));
572 }
573
574 public void testAxisAttribute() {
575
576 assertXPathValue(context, "count(@*)", new Double(21.0));
577
578
579 assertXPathValueLenient(context, "@foo", null);
580 }
581
582
583
584
585
586 public void testAttributeName() {
587 assertXPathValue(context, "nestedBean[@name = 'int']", new Integer(1));
588
589 assertXPathPointer(
590 context,
591 "nestedBean[@name = 'int']",
592 "/nestedBean/int");
593 }
594
595 public void testAttributeLang() {
596
597 assertXPathValue(context, "@xml:lang", "en-US");
598
599 assertXPathValue(context, "count(@xml:*)", new Double(1));
600
601 assertXPathValue(context, "lang('en')", Boolean.TRUE);
602
603 assertXPathValue(context, "lang('fr')", Boolean.FALSE);
604 }
605
606 public void testCoreFunctions() {
607
608 assertXPathValue(context, "boolean(boolean)", Boolean.TRUE);
609
610 assertXPathValue(context, "boolean(boolean = false())", Boolean.TRUE);
611
612 assertXPathValue(
613 context,
614 "boolean(integers[position() < 3])",
615 Boolean.TRUE);
616
617 assertXPathValue(
618 context,
619 "boolean(integers[position() > 4])",
620 Boolean.FALSE);
621
622 assertXPathValue(context, "sum(integers)", new Double(10));
623
624 assertXPathValueAndPointer(
625 context,
626 "integers[last()]",
627 new Integer(4),
628 "/integers[4]");
629
630 assertXPathValueAndPointer(
631 context,
632 "//strings[last()]",
633 "String 3",
634 "/beans[1]/strings[3]");
635 }
636
637 public void testBooleanPredicate() {
638
639
640
641
642
643 assertXPathValue(context, "beans[int > 2]/name", "Name 2");
644
645 assertXPathValueIterator(
646 context,
647 "beans[int > 2]/name",
648 list("Name 2"));
649
650 assertXPathValueIterator(
651 context,
652 "beans[int >= 1]/name",
653 list("Name 1", "Name 2"));
654
655 assertXPathValueIterator(
656 context,
657 "beans[int < 2]/name",
658 list("Name 1"));
659
660 assertXPathValueIterator(
661 context,
662 "beans[int <= 3]/name",
663 list("Name 1", "Name 2"));
664
665 assertXPathValueIterator(
666 context,
667 "beans[1]/strings[string-length() = 8]",
668 list("String 1", "String 2", "String 3"));
669
670
671 assertXPathValueIterator(
672 context,
673 "//self::node()[name = 'Name 0']/name",
674 list("Name 0"));
675
676
677 assertXPathValue(
678 context,
679 "beans/strings[name(.)='strings'][2]",
680 "String 2");
681
682
683 assertXPathValueIterator(
684 context,
685 "//self::node()[name(.) = concat('n', 'a', 'm', 'e')]",
686 list(
687 "Name 1",
688 "Name 2",
689 "Name 3",
690 "Name 6",
691 "Name 0",
692 "Name 5",
693 "Name 4"));
694
695 assertXPathValueIterator(
696 context,
697 "integers[position()<3]",
698 list(new Integer(1), new Integer(2)));
699
700 context.getVariables().declareVariable(
701 "temp",
702 context.getValue("beans"));
703
704 assertXPathValueIterator(
705 context,
706 "$temp[int < 2]/int",
707 list(new Integer(1)));
708 }
709
710 public void testDocumentOrder() {
711 assertDocumentOrder(context, "boolean", "int", -1);
712
713 assertDocumentOrder(context, "integers[1]", "integers[2]", -1);
714
715 assertDocumentOrder(context, "integers[1]", "integers[1]", 0);
716
717 assertDocumentOrder(context, "nestedBean/int", "nestedBean", 1);
718
719 assertDocumentOrder(
720 context,
721 "nestedBean/int",
722 "nestedBean/strings",
723 -1);
724
725 assertDocumentOrder(context, "nestedBean/int", "object/int", -1);
726 }
727
728 public void testSetPropertyValue() {
729
730 assertXPathSetValue(context, "int", new Integer(2));
731
732
733 assertXPathSetValue(context, "int", "3", new Integer(3));
734
735
736 assertXPathSetValue(context, "int", new int[] { 4 }, new Integer(4));
737
738
739 assertXPathSetValue(context, "@int", new Integer(10));
740 }
741
742 public void testSetCollectionElement() {
743
744 assertXPathSetValue(context, "integers[2]", new Integer(5));
745
746
747 assertXPathSetValue(
748 context,
749 "integers[2]",
750 new int[] { 6 },
751 new Integer(6));
752 }
753
754 public void testSetContextDependentNode() {
755
756 assertXPathSetValue(
757 context,
758 "integers[position() = 1]",
759 new Integer(8));
760
761
762 assertXPathSetValue(
763 context,
764 "beans[name = 'Name 1']/int",
765 new Integer(9));
766
767 }
768
769 public void testSetNonPrimitiveValue() {
770
771 assertXPathSetValue(context, "beans[2]", null);
772
773
774 context.setValue("beans[2]", new NestedTestBean("Name 9"));
775
776 assertEquals(
777 "Modified <" + "beans[2]/name" + ">",
778 "Name 9",
779 context.getValue("beans[2]/name"));
780 }
781
782 public void testCreatePath() {
783 context.setValue("nestedBean", null);
784
785
786 assertXPathCreatePath(
787 context,
788 "/nestedBean/int",
789 new Integer(1),
790 "/nestedBean/int");
791
792 boolean ex = false;
793 try {
794 assertXPathCreatePath(
795 context,
796 "/nestedBean/beans[last() + 1]",
797 new Integer(1),
798 "/nestedBean/beans[last() + 1]");
799 }
800 catch (Exception e) {
801 ex = true;
802 }
803 assertTrue("Exception thrown on invalid path for creation", ex);
804
805 }
806
807 public void testCreatePathAndSetValue() {
808 context.setValue("nestedBean", null);
809
810
811 assertXPathCreatePathAndSetValue(
812 context,
813 "/nestedBean/int",
814 new Integer(2),
815 "/nestedBean/int");
816 }
817
818 public void testCreatePathExpandNewCollection() {
819 context.setValue("beans", null);
820
821
822
823 assertXPathCreatePath(
824 context,
825 "/beans[2]/int",
826 new Integer(1),
827 "/beans[2]/int");
828 }
829
830 public void testCreatePathAndSetValueExpandNewCollection() {
831 context.setValue("beans", null);
832
833
834
835 assertXPathCreatePathAndSetValue(
836 context,
837 "/beans[2]/int",
838 new Integer(2),
839 "/beans[2]/int");
840 }
841
842 public void testCreatePathExpandExistingCollection() {
843
844
845 assertXPathCreatePathAndSetValue(
846 context,
847 "/integers[5]",
848 new Integer(3),
849 "/integers[5]");
850 }
851
852 public void testCreatePathExpandExistingCollectionAndSetProperty() {
853
854 assertXPathCreatePath(
855 context,
856 "/beans[3]/int",
857 new Integer(1),
858 "/beans[3]/int");
859 }
860
861 public void testCreatePathAndSetValueExpandExistingCollection() {
862
863 assertXPathCreatePathAndSetValue(
864 context,
865 "/beans[3]/int",
866 new Integer(2),
867 "/beans[3]/int");
868 }
869
870 public void testCreatePathCreateBeanExpandCollection() {
871 context.setValue("nestedBean", null);
872
873
874
875 assertXPathCreatePath(
876 context,
877 "/nestedBean/strings[2]",
878 "String 2",
879 "/nestedBean/strings[2]");
880 }
881
882 public void testCreatePathAndSetValueCreateBeanExpandCollection() {
883 context.setValue("nestedBean", null);
884
885
886
887 assertXPathCreatePathAndSetValue(
888 context,
889 "/nestedBean/strings[2]",
890 "Test",
891 "/nestedBean/strings[2]");
892 }
893
894 public void testRemovePathPropertyValue() {
895
896 context.removePath("nestedBean/int");
897 assertEquals(
898 "Remove property value",
899 new Integer(0),
900 context.getValue("nestedBean/int"));
901 }
902
903 public void testRemovePathArrayElement() {
904
905 context.removePath("nestedBean/strings[1]");
906 assertEquals(
907 "Remove array element",
908 "String 2",
909 context.getValue("nestedBean/strings[1]"));
910 }
911
912 public void testRemoveAllArrayElements() {
913 context.removeAll("nestedBean/strings");
914 assertXPathValueIterator(
915 context,
916 "nestedBean/strings",
917 list());
918 }
919
920 public void testRemoveAllListElements() {
921 context.removeAll("list");
922 assertXPathValueIterator(
923 context,
924 "list",
925 this instanceof DynaBeanModelTest ? list(null, null, null) : list());
926 }
927
928 public void testRemoveAllMapEntries() {
929 context.removeAll("map/*");
930 assertXPathValue(
931 context,
932 "map",
933 Collections.EMPTY_MAP);
934 }
935
936 public void testRemovePathBeanValue() {
937 context.removePath("nestedBean");
938 assertEquals(
939 "Remove collection element",
940 null,
941 context.getValue("nestedBean"));
942 }
943
944 public void testRelativeContextRelativePath() {
945 JXPathContext relative =
946 context.getRelativeContext(context.getPointer("nestedBean"));
947
948 assertXPathValueAndPointer(relative,
949 "int",
950 new Integer(1),
951 "/nestedBean/int");
952 }
953
954 public void testRelativeContextAbsolutePath() {
955 JXPathContext relative =
956 context.getRelativeContext(context.getPointer("nestedBean"));
957
958 assertXPathValueAndPointer(relative,
959 "/integers[2]",
960 new Integer(2),
961 "/integers[2]");
962 }
963
964 public void testRelativeContextParent() {
965 JXPathContext relative =
966 context.getRelativeContext(context.getPointer("nestedBean"));
967
968 assertXPathValueAndPointer(relative,
969 "../integers[2]",
970 new Integer(2),
971 "/integers[2]");
972 }
973
974 public void testRelativeContextInheritance() {
975 context.setFunctions(new ClassFunctions(TestFunctions.class, "test"));
976 JXPathContext relative =
977 context.getRelativeContext(context.getPointer("nestedBean"));
978
979 assertXPathValue(relative,
980 "test:countPointers(strings)",
981 new Integer(3));
982 }
983 }