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