    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.dynamic;
    17
    18  import java.util.ArrayList;
    19  import java.util.HashMap;
    20  import java.util.List;
    21  import java.util.Map;
    22
    23  import org.apache.commons.jxpath.JXPathContext;
    24  import org.apache.commons.jxpath.JXPathTestCase;
    25  import org.apache.commons.jxpath.TestBean;
    26
    27  /***
    28   * @todo more iterator testing with maps
    29   *
    30   * @author Dmitri Plotnikov
    31   * @version $Revision: 1.8 $ $Date: 2004/02/29 14:17:45 $
    32   */
    33
    34  public class DynamicPropertiesModelTest extends JXPathTestCase {
    35      private static boolean enabled = true;
    36      private JXPathContext context;
    37
    38      /***
    39       * Construct a new instance of this test case.
    40       *
    41       * @param name Name of the test case
    42       */
    43      public DynamicPropertiesModelTest(String name) {
    44          super(name);
    45      }
    46
    47      public void setUp() {
    48          if (context == null) {
    49              context = JXPathContext.newContext(new TestBean());
    50              context.setFactory(new TestDynamicPropertyFactory());
    51          }
    52      }
    53
    54      public void testAxisChild() {
    55          assertXPathValue(context, "map/Key1", "Value 1");
    56
    57          assertXPathPointer(context, "map/Key1", "/map[@name='Key1']");
    58
    59          assertXPathValue(context, "map/Key2/name", "Name 6");
    60
    61          assertXPathPointer(context, "map/Key2/name", "/map[@name='Key2']/name");
    62      }
    63
    64      public void testAxisDescendant() {
    65          assertXPathValue(context, "//Key1", "Value 1");
    66      }
    67
    68      /***
    69       * Testing the pseudo-attribute "name" that dynamic property
    70       * objects appear to have.
    71       */
    72      public void testAttributeName() {
    73          assertXPathValue(context, "map[@name = 'Key1']", "Value 1");
    74
    75          assertXPathPointer(
    76              context,
    77              "map[@name = 'Key1']",
    78              "/map[@name='Key1']");
    79
    80          assertXPathPointerLenient(
    81              context,
    82              "map[@name = 'Key&quot;&apos;&quot;&apos;1']",
    83              "/map[@name='Key&quot;&apos;&quot;&apos;1']");
    84
    85          assertXPathValue(context, "/.[@name='map']/Key2/name", "Name 6");
    86
    87          assertXPathPointer(
    88              context,
    89              "/.[@name='map']/Key2/name",
    90              "/map[@name='Key2']/name");
    91
    92          // Bean in a map
    93          assertXPathValue(context, "/map[@name='Key2'][@name='name']", "Name 6");
    94
    95          assertXPathPointer(
    96              context,
    97              "/map[@name='Key2'][@name='name']",
    98              "/map[@name='Key2']/name");
    99
    100         // Map in a bean in a map
    101         assertXPathValue(
    102             context,
    103             "/.[@name='map'][@name='Key2'][@name='name']",
    104             "Name 6");
    105
    106         assertXPathPointer(
    107             context,
    108             "/.[@name='map'][@name='Key2'][@name='name']",
    109             "/map[@name='Key2']/name");
    110
    111         ((Map)context.getValue("map")).put("Key:3", "value3");
    112
    113         assertXPathValueAndPointer(
    114             context,
    115             "/map[@name='Key:3']",
    116             "value3",
    117             "/map[@name='Key:3']");
    118
    119         assertXPathValueAndPointer(
    120             context,
    121             "/map[@name='Key:4:5']",
    122             null,
    123             "/map[@name='Key:4:5']");
    124     }
    125
    126     public void testSetPrimitiveValue() {
    127         assertXPathSetValue(context, "map/Key1", new Integer(6));
    128     }
    129
    130     public void testSetCollection() {
    131         // See if we can assign a whole collection
    132         context.setValue(
    133             "map/Key1",
    134             new Integer[] { new Integer(7), new Integer(8)});
    135
    136         // And then an element in that collection
    137         assertXPathSetValue(context, "map/Key1[1]", new Integer(9));
    138     }
    139
    140     /***
    141      * The key does not exist, but the assignment should succeed anyway,
    142      * because you should always be able to store anything in a Map.
    143      */
    144     public void testSetNewKey() {
    145         // Using a "simple" path
    146         assertXPathSetValue(context, "map/Key4", new Integer(7));
    147
    148         // Using a "non-simple" path
    149         assertXPathPointerLenient(context, "//map/Key5", "/map/Key5");
    150
    151         assertXPathSetValue(context, "//map/Key5", new Integer(8));
    152     }
    153
    154     public void testCreatePath() {
    155         TestBean bean = (TestBean) context.getContextBean();
    156         bean.setMap(null);
    157
    158         // Calls factory.createObject(..., testBean, "map"), then
    159         // sets the value
    160         assertXPathCreatePath(
    161             context,
    162             "/map[@name='TestKey1']",
    163             "",
    164             "/map[@name='TestKey1']");
    165     }
    166
    167     public void testCreatePathAndSetValue() {
    168         TestBean bean = (TestBean) context.getContextBean();
    169         bean.setMap(null);
    170
    171         // Calls factory.createObject(..., testBean, "map"), then
    172         // sets the value
    173         assertXPathCreatePathAndSetValue(
    174             context,
    175             "/map[@name='TestKey1']",
    176             "Test",
    177             "/map[@name='TestKey1']");
    178     }
    179
    180     public void testCreatePathCreateBean() {
    181         TestBean bean = (TestBean) context.getContextBean();
    182         bean.setMap(null);
    183
    184         // Calls factory.createObject(..., testBean, "map"), then
    185         // then factory.createObject(..., map, "TestKey2"), then
    186         // sets the value
    187         assertXPathCreatePath(
    188             context,
    189             "/map[@name='TestKey2']/int",
    190             new Integer(1),
    191             "/map[@name='TestKey2']/int");
    192     }
    193
    194     public void testCreatePathAndSetValueCreateBean() {
    195         TestBean bean = (TestBean) context.getContextBean();
    196         bean.setMap(null);
    197
    198         // Calls factory.createObject(..., testBean, "map"), then
    199         // then factory.createObject(..., map, "TestKey2"), then
    200         // sets the value
    201         assertXPathCreatePathAndSetValue(
    202             context,
    203             "/map[@name='TestKey2']/int",
    204             new Integer(4),
    205             "/map[@name='TestKey2']/int");
    206     }
    207
    208     public void testCreatePathCollectionElement() {
    209         TestBean bean = (TestBean) context.getContextBean();
    210         bean.setMap(null);
    211
    212         assertXPathCreatePath(
    213             context,
    214             "/map/TestKey3[2]",
    215             null,
    216             "/map[@name='TestKey3'][2]");
    217
    218         // Should be the same as the one before
    219         assertXPathCreatePath(
    220             context,
    221             "/map[@name='TestKey3'][3]",
    222             null,
    223             "/map[@name='TestKey3'][3]");
    224     }
    225
    226     public void testCreatePathAndSetValueCollectionElement() {
    227         TestBean bean = (TestBean) context.getContextBean();
    228         bean.setMap(null);
    229
    230         assertXPathCreatePathAndSetValue(
    231             context,
    232             "/map/TestKey3[2]",
    233             "Test1",
    234             "/map[@name='TestKey3'][2]");
    235
    236         // Should be the same as the one before
    237         assertXPathCreatePathAndSetValue(
    238             context,
    239             "/map[@name='TestKey3'][3]",
    240             "Test2",
    241             "/map[@name='TestKey3'][3]");
    242     }
    243
    244     public void testCreatePathNewCollectionElement() {
    245         TestBean bean = (TestBean) context.getContextBean();
    246         bean.setMap(null);
    247
    248         // Create an element of a dynamic map element, which is a collection
    249         assertXPathCreatePath(
    250             context,
    251             "/map/TestKey4[1]/int",
    252             new Integer(1),
    253             "/map[@name='TestKey4'][1]/int");
    254
    255         bean.getMap().remove("TestKey4");
    256
    257         // Should be the same as the one before
    258         assertXPathCreatePath(
    259             context,
    260             "/map/TestKey4[1]/int",
    261             new Integer(1),
    262             "/map[@name='TestKey4'][1]/int");
    263     }
    264
    265     public void testCreatePathAndSetValueNewCollectionElement() {
    266         TestBean bean = (TestBean) context.getContextBean();
    267         bean.setMap(null);
    268
    269         // Create an element of a dynamic map element, which is a collection
    270         assertXPathCreatePathAndSetValue(
    271             context,
    272             "/map/TestKey4[1]/int",
    273             new Integer(2),
    274             "/map[@name='TestKey4'][1]/int");
    275
    276         bean.getMap().remove("TestKey4");
    277
    278         // Should be the same as the one before
    279         assertXPathCreatePathAndSetValue(
    280             context,
    281             "/map/TestKey4[1]/int",
    282             new Integer(3),
    283             "/map[@name='TestKey4'][1]/int");
    284     }
    285
    286     public void testRemovePath() {
    287         TestBean bean = (TestBean) context.getContextBean();
    288         bean.getMap().put("TestKey1", "test");
    289
    290         // Remove dynamic property
    291         context.removePath("map[@name = 'TestKey1']");
    292         assertEquals(
    293             "Remove dynamic property value",
    294             null,
    295             context.getValue("map[@name = 'TestKey1']"));
    296     }
    297
    298     public void testRemovePathArrayElement() {
    299         TestBean bean = (TestBean) context.getContextBean();
    300
    301         bean.getMap().put("TestKey2", new String[] { "temp1", "temp2" });
    302         context.removePath("map[@name = 'TestKey2'][1]");
    303         assertEquals(
    304             "Remove dynamic property collection element",
    305             "temp2",
    306             context.getValue("map[@name = 'TestKey2'][1]"));
    307     }
    308
    309     public void testCollectionOfMaps() {
    310         TestBean bean = (TestBean) context.getContextBean();
    311         List list = new ArrayList();
    312
    313         bean.getMap().put("stuff", list);
    314
    315         Map m = new HashMap();
    316         m.put("fruit", "apple");
    317         list.add(m);
    318
    319         m = new HashMap();
    320         m.put("berry", "watermelon");
    321         list.add(m);
    322
    323         m = new HashMap();
    324         m.put("fruit", "banana");
    325         list.add(m);
    326
    327         assertXPathValueIterator(
    328             context,
    329             "/map/stuff/fruit",
    330             list("apple", "banana"));
    331
    332         assertXPathValueIterator(
    333             context,
    334             "/map/stuff[@name='fruit']",
    335             list("apple", "banana"));
    336     }
    337
    338     public void testMapOfMaps() {
    339         TestBean bean = (TestBean) context.getContextBean();
    340
    341         Map fruit = new HashMap();
    342         fruit.put("apple", "green");
    343         fruit.put("orange", "red");
    344
    345         Map meat = new HashMap();
    346         meat.put("pork", "pig");
    347         meat.put("beef", "cow");
    348
    349         bean.getMap().put("fruit", fruit);
    350         bean.getMap().put("meat", meat);
    351
    352         assertXPathPointer(
    353             context,
    354             "//beef",
    355             "/map[@name='meat'][@name='beef']");
    356
    357         assertXPathPointer(
    358             context,
    359             "map//apple",
    360             "/map[@name='fruit'][@name='apple']");
    361
    362         // Ambiguous search - will return nothing
    363         assertXPathPointerLenient(context, "map//banana", "null()");
    364
    365         // Unambiguous, even though the particular key is missing
    366         assertXPathPointerLenient(
    367             context,
    368             "//fruit/pear",
    369             "/map[@name='fruit']/pear");
    370     }
    371 }