    1   /*
    2    * Copyright 1999-2004 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    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  /***
    36   * Abstract superclass for Bean access with JXPath.
    37   *
    38   * @author Dmitri Plotnikov
    39   * @version $Revision: 1.19 $ $Date: 2004/02/29 14:17:45 $
    40   */
    41
    42  public abstract class BeanModelTestCase extends JXPathTestCase {
    43      private JXPathContext context;
    44
    45      /***
    46       * Construct a new instance of this test case.
    47       *
    48       * @param name Name of the test case
    49       */
    50      public BeanModelTestCase(String name) {
    51          super(name);
    52      }
    53
    54      public void setUp() {
    55  //        if (context == null) {
    56              context = JXPathContext.newContext(createContextBean());
    57              context.setLocale(Locale.US);
    58              context.setFactory(getAbstractFactory());
    59  //        }
    60      }
    61
    62      protected abstract Object createContextBean();
    63      protected abstract AbstractFactory getAbstractFactory();
    64
    65      /***
    66       * Test property iterators, the core of the graph traversal engine
    67       */
    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     /***
    130      * Test property iterators with multiple properties returned
    131      */
    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 //            System.err.println("LOC: " + it.getCurrentNodePointer());
    171             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     /***
    252      * Test contributed by Kate Dvortsova
    253      */
    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         // Test setting via context
    261         context.setValue("/beans[2]/name", "Name 2 set");
    262         assertXPathValue(context, "/beans[2]/name", "Name 2 set");
    263
    264         // Restore original value
    265         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             // fails right here, the value isn't getting set in the bean.
    278             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         // ancestor::
    295         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         // Count elements in a child collection
    316         assertXPathValue(context, "count(set)", new Double(3));
    317
    318 //        assertXPathValue(context,"boolean/class/name", "java.lang.Boolean");
    319
    320         // Child with namespace - should not find any
    321         assertXPathValueIterator(context, "foo:boolean", list());
    322
    323         // Count all children with a wildcard
    324         assertXPathValue(context, "count(*)", new Double(21));
    325
    326         // Same, constrained by node type = node()
    327         assertXPathValue(context, "count(child::node())", new Double(21));
    328     }
    329
    330     public void testAxisChildNestedBean() {
    331         // Nested bean
    332         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         // Find the first match
    389         assertXPathValue(context, "beans/strings[2]", "String 2");
    390
    391         // Indexing in a set collected from a UnionContext
    392         assertXPathValue(context, "(beans/strings[2])[1]", "String 2");
    393     }
    394
    395     public void testAxisDescendant() {
    396         // descendant::
    397         assertXPathValue(context, "count(descendant::node())", new Double(65));
    398
    399         // Should not find any descendants with name root
    400         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         // descendant-or-self::
    407         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         // Same - abbreviated syntax
    420         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         // See that it actually finds self
    433         assertXPathValue(
    434             context,
    435             "count(descendant-or-self::root)",
    436             new Double(1));
    437
    438         // Combine descendant-or-self:: and and self::
    439         assertXPathValue(context, "count(nestedBean//.)", new Double(7));
    440
    441         // Combine descendant-or-self:: and and self::name
    442         assertXPathValue(context, "count(//self::beans)", new Double(2));
    443
    444         // Count all nodes in the tree
    445         assertXPathValue(
    446             context,
    447             "count(descendant-or-self::node())",
    448             new Double(66));
    449
    450     }
    451
    452     public void testAxisFollowing() {
    453         // following::
    454         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         // following-sibling::
    467         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         // Combine parent:: and following-sibling::
    478         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         // Combine descendant:: and following-sibling::
    489         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         // parent::
    502         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         // preceding::
    516         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         // preceding-sibling::
    529         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         // self::
    547         assertXPathValue(context, "self::node() = /", Boolean.TRUE);
    548
    549         assertXPathValue(context, "self::root = /", Boolean.TRUE);
    550     }
    551
    552     public void testUnion() {
    553         // Union - note corrected document order
    554         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         // Note that the following is different from "integer[2]" -
    577         // it is a filter expression
    578         assertXPathValue(context, "(integers)[2]", new Integer(2));
    579     }
    580
    581     public void testAxisAttribute() {
    582         // Attributes are just like children to beans
    583         assertXPathValue(context, "count(@*)", new Double(21.0));
    584
    585         // Unknown attribute
    586         assertXPathValueLenient(context, "@foo", null);
    587     }
    588
    589     /***
    590      * Testing the pseudo-attribute "name" that java beans
    591      * objects appear to have.
    592      */
    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         // use child axis
    646
    647         // bean[1]/int = 1
    648         // bean[2]/int = 3
    649
    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         // use some fancy axis and the child axis in the predicate
    678         assertXPathValueIterator(
    679             context,
    680             "//self::node()[name = 'Name 0']/name",
    681             list("Name 0"));
    682
    683         // use context-dependent function in the predicate
    684         assertXPathValue(
    685             context,
    686             "beans/strings[name(.)='strings'][2]",
    687             "String 2");
    688
    689         // use context-independent function in the predicate
    690         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         // Simple property
    737         assertXPathSetValue(context, "int", new Integer(2));
    738
    739         // Simple property with conversion from string
    740         assertXPathSetValue(context, "int", "3", new Integer(3));
    741
    742         // Simple property with conversion from array
    743         assertXPathSetValue(context, "int", new int[] { 4 }, new Integer(4));
    744
    745         // Attribute (which is the same as a child for beans
    746         assertXPathSetValue(context, "@int", new Integer(10));
    747     }
    748
    749     public void testSetCollectionElement() {
    750         // Collection element
    751         assertXPathSetValue(context, "integers[2]", new Integer(5));
    752
    753         // Collection element with conversion
    754         assertXPathSetValue(
    755             context,
    756             "integers[2]",
    757             new int[] { 6 },
    758             new Integer(6));
    759     }
    760
    761     public void testSetContextDependentNode() {
    762         // Find node without using SimplePathInterpreter
    763         assertXPathSetValue(
    764             context,
    765             "integers[position() = 1]",
    766             new Integer(8));
    767
    768         // Find node without using SimplePathInterpreter and set its property
    769         assertXPathSetValue(
    770             context,
    771             "beans[name = 'Name 1']/int",
    772             new Integer(9));
    773
    774     }
    775
    776     public void testSetNonPrimitiveValue() {
    777         // First, let's see if we can set a collection element to null
    778         assertXPathSetValue(context, "beans[2]", null);
    779
    780         // Now, assign it a whole bean
    781         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         // Calls factory.createObject(..., TestBean, "nestedBean")
    793         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         // Calls factory.createObject(..., TestBean, "nestedBean")
    818         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         // Calls factory.createObject(..., testBean, "beans", 2),
    829         // then  factory.createObject(..., testBean, "beans", 2)
    830         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         // Calls factory.createObject(..., testBean, "beans", 2),
    841         // then factory.createObject(..., testBean, "beans", 2)
    842         assertXPathCreatePathAndSetValue(
    843             context,
    844             "/beans[2]/int",
    845             new Integer(2),
    846             "/beans[2]/int");
    847     }
    848
    849     public void testCreatePathExpandExistingCollection() {
    850         // Calls factory.createObject(..., TestBean, "integers", 5)
    851         // to expand collection
    852         assertXPathCreatePathAndSetValue(
    853             context,
    854             "/integers[5]",
    855             new Integer(3),
    856             "/integers[5]");
    857     }
    858
    859     public void testCreatePathExpandExistingCollectionAndSetProperty() {
    860         // Another, but the collection already exists
    861         assertXPathCreatePath(
    862             context,
    863             "/beans[3]/int",
    864             new Integer(1),
    865             "/beans[3]/int");
    866     }
    867
    868     public void testCreatePathAndSetValueExpandExistingCollection() {
    869         // Another, but the collection already exists
    870         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         // Calls factory.createObject(..., TestBean, "nestedBean")
    881         // Calls factory.createObject(..., nestedBean, "strings", 2)
    882         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         // Calls factory.createObject(..., TestBean, "nestedBean")
    893         // Calls factory.createObject(..., nestedBean, "strings", 2)
    894         assertXPathCreatePathAndSetValue(
    895             context,
    896             "/nestedBean/strings[2]",
    897             "Test",
    898             "/nestedBean/strings[2]");
    899     }
    900
    901     public void testRemovePathPropertyValue() {
    902         // Remove property value
    903         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         // Assigns a new array to the property
    912         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 }