View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.jexl3.junit.Asserter;
25  import org.junit.Before;
26  import org.junit.Test;
27  
28  
29  /**
30   * Tests for array access operator []
31   *
32   * @since 2.0
33   */
34  @SuppressWarnings({"UnnecessaryBoxing", "AssertEqualsBetweenInconvertibleTypes"})
35  public class ArrayAccessTest extends JexlTestCase {
36  
37      private Asserter asserter;
38  
39      private static final String GET_METHOD_STRING = "GetMethod string";
40  
41      // Needs to be accessible by Foo.class
42      static final String[] GET_METHOD_ARRAY =
43          new String[] { "One", "Two", "Three" };
44  
45      // Needs to be accessible by Foo.class
46      static final String[][] GET_METHOD_ARRAY2 =
47          new String[][] { {"One", "Two", "Three"},{"Four", "Five", "Six"} };
48  
49      public ArrayAccessTest() {
50          super("ArrayAccessTest");
51      }
52  
53      @Override
54      @Before
55      public void setUp() {
56          asserter = new Asserter(JEXL);
57      }
58  
59      /**
60       * test simple array access
61       */
62      @Test
63      public void testArrayAccess() throws Exception {
64  
65          /*
66           * test List access
67           */
68  
69          final List<Integer> l = new ArrayList<>();
70          l.add(new Integer(1));
71          l.add(new Integer(2));
72          l.add(new Integer(3));
73  
74          asserter.setVariable("list", l);
75  
76          asserter.assertExpression("list[1]", new Integer(2));
77          asserter.assertExpression("list[1+1]", new Integer(3));
78          asserter.setVariable("loc", new Integer(1));
79          asserter.assertExpression("list[loc+1]", new Integer(3));
80  
81          /*
82           * test array access
83           */
84  
85          final String[] args = { "hello", "there" };
86          asserter.setVariable("array", args);
87          asserter.assertExpression("array[0]", "hello");
88  
89          /*
90           * to think that this was an intentional syntax...
91           */
92          asserter.assertExpression("array.0", "hello");
93  
94          /*
95           * test map access
96           */
97          final Map<String, String> m = new HashMap<>();
98          m.put("foo", "bar");
99  
100         asserter.setVariable("map", m);
101         asserter.setVariable("key", "foo");
102 
103         asserter.assertExpression("map[\"foo\"]", "bar");
104         asserter.assertExpression("map[key]", "bar");
105 
106         /*
107          * test bean access
108          */
109         asserter.setVariable("foo", new Foo());
110         asserter.assertExpression("foo[\"bar\"]", GET_METHOD_STRING);
111         asserter.assertExpression("foo[\"bar\"] == foo.bar", Boolean.TRUE);
112     }
113 
114     /**
115      * test some simple double array lookups
116      */
117     @Test
118     public void testDoubleArrays() throws Exception {
119         final Object[][] foo = new Object[2][2];
120 
121         foo[0][0] = "one";
122         foo[0][1] = "two";
123         asserter.setVariable("foo", foo);
124         asserter.assertExpression("foo[0][1]", "two");
125         asserter.assertExpression("foo[0][1] = 'three'", "three");
126         asserter.assertExpression("foo[0][1]", "three");
127 
128         foo[0][0] = "one";
129         foo[0][1] = "two";
130         asserter.assertExpression("foo.0[1]", "two");
131         asserter.assertExpression("foo.0[1] = 'three'", "three");
132         asserter.assertExpression("foo.0[1]", "three");
133 
134         foo[0][0] = "one";
135         foo[0][1] = "two";
136         asserter.assertExpression("foo.0.'1'", "two");
137         asserter.assertExpression("foo.0.'1' = 'three'", "three");
138         asserter.assertExpression("foo.0.'1'", "three");
139 
140         foo[0][0] = "one";
141         foo[0][1] = "two";
142         asserter.assertExpression("foo.'0'.'1'", "two");
143         asserter.assertExpression("foo.'0'.'1' = 'three'", "three");
144         asserter.assertExpression("foo.'0'.'1'", "three");
145 
146 
147         foo[0][0] = "one";
148         foo[0][1] = "two";
149         asserter.assertExpression("foo.0.1", "two");
150         asserter.assertExpression("foo.0.1 = 'three'", "three");
151         asserter.assertExpression("foo.0.1", "three");
152     }
153 
154     @Test
155     public void testDoubleMaps() throws Exception {
156         final Map<Object, Map<Object, Object>> foo = new HashMap<>();
157         final Map<Object, Object> foo0 = new HashMap<>();
158         foo.put(0, foo0);
159         foo0.put(0, "one");
160         foo0.put(1, "two");
161         foo0.put("3.0", "three");
162         asserter.setVariable("foo", foo);
163         asserter.assertExpression("foo[0][1]", "two");
164         asserter.assertExpression("foo[0][1] = 'three'", "three");
165         asserter.assertExpression("foo[0][1]", "three");
166         asserter.assertExpression("foo[0]['3.0']", "three");
167 
168         foo0.put(0, "one");
169         foo0.put(1, "two");
170         asserter.assertExpression("foo.0[1]", "two");
171         asserter.assertExpression("foo.0[1] = 'three'", "three");
172         asserter.assertExpression("foo.0[1]", "three");
173         asserter.assertExpression("foo.0['3.0']", "three");
174 
175         foo0.put(0, "one");
176         foo0.put(1, "two");
177         asserter.assertExpression("foo.0.'1'", "two");
178         asserter.assertExpression("foo.0.'1' = 'three'", "three");
179         asserter.assertExpression("foo.0.'1'", "three");
180 
181         foo0.put(0, "one");
182         foo0.put(1, "two");
183         asserter.assertExpression("foo.'0'.'1'", "two");
184         asserter.assertExpression("foo.'0'.'1' = 'three'", "three");
185         asserter.assertExpression("foo.'0'.'1'", "three");
186 
187         foo0.put(0, "one");
188         foo0.put(1, "two");
189         asserter.assertExpression("foo.0.1", "two");
190         asserter.assertExpression("foo.0.1 = 'three'", "three");
191         asserter.assertExpression("foo.0.1", "three");
192     }
193 
194     @Test
195     public void testArrayProperty() throws Exception {
196         final Foo foo = new Foo();
197 
198         asserter.setVariable("foo", foo);
199 
200         asserter.assertExpression("foo.array[1]", GET_METHOD_ARRAY[1]);
201         asserter.assertExpression("foo.array.1", GET_METHOD_ARRAY[1]);
202         asserter.assertExpression("foo.array2[1][1]", GET_METHOD_ARRAY2[1][1]);
203         asserter.assertExpression("foo.array2[1].1", GET_METHOD_ARRAY2[1][1]);
204     }
205 
206     // This is JEXL-26
207     @Test
208     public void testArrayAndDottedConflict() throws Exception {
209         final Object[] objects = new Object[] {"an", "array", new Long(0)};
210         asserter.setStrict(false);
211         asserter.setSilent(true);
212         asserter.setVariable("objects", objects);
213         asserter.setVariable("status", "Enabled");
214         asserter.assertExpression("objects[1].status", null);
215         asserter.assertExpression("objects.1.status", null);
216 
217         asserter.setVariable("base.status", "Ok");
218         asserter.assertExpression("base.objects[1].status", null);
219         asserter.assertExpression("base.objects.1.status", null);
220     }
221 
222     @Test
223     public void testArrayIdentifierParsing() throws Exception {
224         final Map<Object, Number> map = new HashMap<>();
225         map.put("00200", -42.42d);
226         map.put(200, 42.42d);
227         asserter.setVariable("objects", map);
228         asserter.assertExpression("objects.get('00200')", -42.42d);
229         asserter.assertExpression("objects.'00200'", -42.42d);
230         asserter.assertExpression("objects.get(200)", 42.42d);
231         asserter.assertExpression("objects.'200'", 42.42d);
232         asserter.assertExpression("objects.200", 42.42d);
233     }
234 
235     @Test
236     public void testArrayMethods() throws Exception {
237         final Object[] objects = new Object[] {"an", "array", new Long(0)};
238 
239         asserter.setVariable("objects", objects);
240         asserter.assertExpression("objects.get(1)", "array");
241         asserter.assertExpression("objects.size()", new Integer(3));
242         // setting an index returns the old value
243         asserter.assertExpression("objects.set(1, 'dion')", "array");
244         asserter.assertExpression("objects[1]", "dion");
245     }
246 
247     @Test
248     public void testArrayArray() throws Exception {
249         final Integer i42 = Integer.valueOf(42);
250         final Integer i43 = Integer.valueOf(43);
251         final String s42 = "fourty-two";
252         final String s43 = "fourty-three";
253         final Object[] foo = new Object[3];
254         foo[0] = foo;
255         foo[1] = i42;
256         foo[2] = s42;
257         asserter.setVariable("foo", foo);
258         asserter.setVariable("zero", Integer.valueOf(0));
259         asserter.setVariable("one", Integer.valueOf(1));
260         asserter.setVariable("two", Integer.valueOf(2));
261         for(int l = 0; l < 2; ++l) {
262             asserter.assertExpression("foo[0]", foo);
263             asserter.assertExpression("foo[0][0]", foo);
264             asserter.assertExpression("foo[1]", foo[1]);
265             asserter.assertExpression("foo[0][1]", foo[1]);
266             asserter.assertExpression("foo[0][1] = 43", i43);
267             asserter.assertExpression("foo[0][1]", i43);
268             asserter.assertExpression("foo[0][1] = 42", i42);
269             asserter.assertExpression("foo[0][1]", i42);
270             asserter.assertExpression("foo[0][0][1]", foo[1]);
271             asserter.assertExpression("foo[0][0][1] = 43", i43);
272             asserter.assertExpression("foo[0][0][1]", i43);
273             asserter.assertExpression("foo[0][0][1] = 42", i42);
274             asserter.assertExpression("foo[0][0][1]", i42);
275             asserter.assertExpression("foo[2]", foo[2]);
276             asserter.assertExpression("foo[0][2]", foo[2]);
277             asserter.assertExpression("foo[0][2] = 'fourty-three'", s43);
278             asserter.assertExpression("foo[0][2]", s43);
279             asserter.assertExpression("foo[0][2] = 'fourty-two'", s42);
280             asserter.assertExpression("foo[0][2]", s42);
281             asserter.assertExpression("foo[0][0][2]", foo[2]);
282             asserter.assertExpression("foo[0][0][2] = 'fourty-three'", s43);
283             asserter.assertExpression("foo[0][0][2]", s43);
284             asserter.assertExpression("foo[0][0][2] = 'fourty-two'", s42);
285             asserter.assertExpression("foo[0][0][2]", s42);
286 
287             asserter.assertExpression("foo[zero]", foo);
288             asserter.assertExpression("foo[zero][zero]", foo);
289             asserter.assertExpression("foo[one]", foo[1]);
290             asserter.assertExpression("foo[zero][one]", foo[1]);
291             asserter.assertExpression("foo[zero][one] = 43", i43);
292             asserter.assertExpression("foo[zero][one]", i43);
293             asserter.assertExpression("foo[zero][one] = 42", i42);
294             asserter.assertExpression("foo[zero][one]", i42);
295             asserter.assertExpression("foo[zero][zero][one]", foo[1]);
296             asserter.assertExpression("foo[zero][zero][one] = 43", i43);
297             asserter.assertExpression("foo[zero][zero][one]", i43);
298             asserter.assertExpression("foo[zero][zero][one] = 42", i42);
299             asserter.assertExpression("foo[zero][zero][one]", i42);
300             asserter.assertExpression("foo[two]", foo[2]);
301             asserter.assertExpression("foo[zero][two]", foo[2]);
302             asserter.assertExpression("foo[zero][two] = 'fourty-three'", s43);
303             asserter.assertExpression("foo[zero][two]", s43);
304             asserter.assertExpression("foo[zero][two] = 'fourty-two'", s42);
305             asserter.assertExpression("foo[zero][two]", s42);
306             asserter.assertExpression("foo[zero][zero][two]", foo[2]);
307             asserter.assertExpression("foo[zero][zero][two] = 'fourty-three'", s43);
308             asserter.assertExpression("foo[zero][zero][two]", s43);
309             asserter.assertExpression("foo[zero][zero][two] = 'fourty-two'", s42);
310             asserter.assertExpression("foo[zero][zero][two]", s42);
311         }
312     }
313 
314     public static class Sample {
315         private int[] array;
316         public void setFoo(final int[] a) {
317             array = a;
318         }
319         public int[] getFoo() {
320             return array;
321         }
322     }
323     @Test
324     public void testArrayGetSet() throws Exception {
325         final Sample bar  = new Sample();
326         bar.setFoo(new int[]{24});
327         asserter.setVariable("bar", bar);
328         asserter.assertExpression("bar.foo[0]", 24);
329         asserter.assertExpression("bar.foo = []", new int[0]);
330         //asserter.assertExpression("bar.foo[0]", 42);
331     }
332 }