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.internal.introspection;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertNotEquals;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertTrue;
23  
24  import java.io.Serializable;
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.commons.jexl3.JexlTestCase;
31  import org.apache.commons.jexl3.internal.Engine;
32  import org.apache.commons.jexl3.introspection.JexlMethod;
33  import org.apache.commons.jexl3.introspection.JexlPropertyGet;
34  import org.apache.commons.jexl3.introspection.JexlPropertySet;
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * Tests for checking introspection discovery.
39   */
40  public class DiscoveryTest extends JexlTestCase {
41      public static class Bean {
42          private String value;
43          private String eulav;
44          private boolean flag;
45  
46          public Bean(final String v, final String e) {
47              value = v;
48              eulav = e;
49              flag = true;
50          }
51  
52          public String getEulav() {
53              return eulav;
54          }
55  
56          public String getValue() {
57              return value;
58          }
59  
60          public boolean isFlag() {
61              return flag;
62          }
63  
64          public void setEulav(final String v) {
65              eulav = v;
66          }
67  
68          public void setFlag(final boolean f) {
69              flag = f;
70          }
71  
72          public void setValue(final String v) {
73              value = v;
74          }
75      }
76  
77      public static class Bulgroz {
78          public Object amb(final Number x) {
79              return -2;
80          }
81          public Object amb(final Serializable x) {
82              return -1;
83          }
84          public Object list(final int x) {
85              return 0;
86          }
87          public Object list(final int x, final int y) {
88              return 4;
89          }
90          public Object list(final int x, final Object...y) {
91              return 3;
92          }
93          public Object list(final Object x) {
94              return 2;
95          }
96          public Object list(final Object x, final Object...y) {
97              return 7;
98          }
99          public Object list(final Object x, final Object y) {
100             return 8;
101         }
102         public Object list(final String x) {
103             return 1;
104         }
105         public Object list(final String x, final Object...y) {
106             return 5;
107         }
108         public Object list(final String x, final String y) {
109             return 6;
110         }
111     }
112 
113     public static class Duck {
114         private String value;
115         private String eulav;
116 
117         public Duck(final String v, final String e) {
118             value = v;
119             eulav = e;
120         }
121 
122         public String get(final String prop) {
123             if ("value".equals(prop)) {
124                 return value;
125             }
126             if ("eulav".equals(prop)) {
127                 return eulav;
128             }
129             return "no such property";
130         }
131 
132         public void set(final String prop, final String v) {
133             if ("value".equals(prop)) {
134                 value = v;
135             } else if ("eulav".equals(prop)) {
136                 eulav = v;
137             }
138         }
139     }
140 
141     public DiscoveryTest() {
142         super("DiscoveryTest");
143     }
144 
145     @Test
146     public void testBeanIntrospection() throws Exception {
147         final Uberspect uber = Engine.getUberspect(null, null);
148         final Bean bean = new Bean("JEXL", "LXEJ");
149 
150         final JexlPropertyGet get = uber.getPropertyGet(bean, "value");
151         final JexlPropertySet set = uber.getPropertySet(bean, "value", "foo");
152         assertTrue(get instanceof PropertyGetExecutor, "bean property getter");
153         assertTrue(set instanceof PropertySetExecutor, "bean property setter");
154         // introspector and uberspect should return same result
155         assertEquals(get, uber.getPropertyGet(bean, "value"));
156         assertEquals(set, uber.getPropertySet(bean, "value", "foo"));
157         // different property should return different setter/getter
158         assertNotEquals(get, uber.getPropertyGet(bean, "eulav"));
159         assertNotEquals(set, uber.getPropertySet(bean, "eulav", "foo"));
160         // setter returns argument
161         final Object bar = set.invoke(bean, "bar");
162         assertEquals("bar", bar);
163         // getter should return last value
164         assertEquals("bar", get.invoke(bean));
165         // tryExecute should succeed on same property
166         final Object quux = set.tryInvoke(bean, "value", "quux");
167         assertEquals("quux", quux);
168         assertEquals("quux", get.invoke(bean));
169         // tryExecute should fail on different property
170         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(bean, "eulav", "nope"));
171 
172     }
173 
174     @Test
175     public void testDuckIntrospection() throws Exception {
176         final Uberspect uber = Engine.getUberspect(null, null);
177         final Duck duck = new Duck("JEXL", "LXEJ");
178 
179         final JexlPropertyGet get = uber.getPropertyGet(duck, "value");
180         final JexlPropertySet set = uber.getPropertySet(duck, "value", "foo");
181         assertTrue(get instanceof DuckGetExecutor, "duck property getter");
182         assertTrue(set instanceof DuckSetExecutor, "duck property setter");
183         // introspector and uberspect should return same result
184         assertEquals(get, uber.getPropertyGet(duck, "value"));
185         assertEquals(set, uber.getPropertySet(duck, "value", "foo"));
186         // different property should return different setter/getter
187         assertNotEquals(get, uber.getPropertyGet(duck, "eulav"));
188         assertNotEquals(set, uber.getPropertySet(duck, "eulav", "foo"));
189         // setter returns argument
190         final Object bar = set.invoke(duck, "bar");
191         assertEquals("bar", bar);
192         // getter should return last value
193         assertEquals("bar", get.invoke(duck));
194         // tryExecute should succeed on same property
195         final Object quux = set.tryInvoke(duck, "value", "quux");
196         assertEquals("quux", quux);
197         assertEquals("quux", get.invoke(duck));
198         // tryExecute should fail on different property
199         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(duck, "eulav", "nope"));
200     }
201 
202     @Test
203     public void testListIntrospection() throws Exception {
204         final Uberspect uber = Engine.getUberspect(null, null);
205         final List<Object> list = new ArrayList<>();
206         list.add("LIST");
207         list.add("TSIL");
208 
209         final JexlPropertyGet get = uber.getPropertyGet(list, 1);
210         final JexlPropertySet set = uber.getPropertySet(list, 1, "foo");
211         assertTrue(get instanceof ListGetExecutor, "list property getter");
212         assertTrue(set instanceof ListSetExecutor, "list property setter");
213         // introspector and uberspect should return same result
214         assertEquals(get, uber.getPropertyGet(list, 1));
215         assertEquals(set, uber.getPropertySet(list, 1, "foo"));
216         // different property should return different setter/getter
217         assertNotEquals(get, uber.getPropertyGet(list, 0));
218         assertNotEquals(get, uber.getPropertySet(list, 0, "foo"));
219         // setter returns argument
220         final Object bar = set.invoke(list, "bar");
221         assertEquals("bar", bar);
222         // getter should return last value
223         assertEquals("bar", get.invoke(list));
224         // tryExecute should succeed on integer property
225         final Object quux = set.tryInvoke(list, 1, "quux");
226         assertEquals("quux", quux);
227         // getter should return last value
228         assertEquals("quux", get.invoke(list));
229         // tryExecute should fail on non-integer property class
230         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(list, "eulav", "nope"));
231     }
232 
233     @Test
234     public void testMapIntrospection() throws Exception {
235         final Uberspect uber = Engine.getUberspect(null, null);
236         final Map<String, Object> map = new HashMap<>();
237         map.put("value", "MAP");
238         map.put("eulav", "PAM");
239 
240         final JexlPropertyGet get = uber.getPropertyGet(map, "value");
241         final JexlPropertySet set = uber.getPropertySet(map, "value", "foo");
242         assertTrue(get instanceof MapGetExecutor, "map property getter");
243         assertTrue(set instanceof MapSetExecutor, "map property setter");
244         // introspector and uberspect should return same result
245         assertEquals(get, uber.getPropertyGet(map, "value"));
246         assertEquals(set, uber.getPropertySet(map, "value", "foo"));
247         // different property should return different setter/getter
248         assertNotEquals(get, uber.getPropertyGet(map, "eulav"));
249         assertNotEquals(get, uber.getPropertySet(map, "eulav", "foo"));
250         // setter returns argument
251         final Object bar = set.invoke(map, "bar");
252         assertEquals("bar", bar);
253         // getter should return last value
254         assertEquals("bar", get.invoke(map));
255         // tryExecute should succeed on same property class
256         final Object quux = set.tryInvoke(map, "value", "quux");
257         assertEquals("quux", quux);
258         // getter should return last value
259         assertEquals("quux", get.invoke(map));
260         // tryExecute should fail on different property class
261         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(map, 1, "nope"));
262     }
263 
264     @Test
265     public void testMethodIntrospection() throws Exception {
266         final Uberspect uber = new Uberspect(null, null);
267         final Bulgroz bulgroz = new Bulgroz();
268         JexlMethod jmethod;
269         Object result;
270         jmethod = uber.getMethod(bulgroz, "list", 0);
271         result = jmethod.invoke(bulgroz, 0);
272         assertEquals(0, result);
273         jmethod = uber.getMethod(bulgroz, "list", "1");
274         result = jmethod.invoke(bulgroz, "1");
275         assertEquals(1, result);
276         jmethod = uber.getMethod(bulgroz, "list", bulgroz);
277         result = jmethod.invoke(bulgroz, bulgroz);
278         assertEquals(2, result);
279         jmethod = uber.getMethod(bulgroz, "list", 1, bulgroz);
280         result = jmethod.invoke(bulgroz, 1, bulgroz);
281         assertEquals(3, result);
282         jmethod = uber.getMethod(bulgroz, "list", 1, bulgroz, bulgroz);
283         result = jmethod.invoke(bulgroz, 1, bulgroz, bulgroz);
284         assertEquals(3, result);
285         jmethod = uber.getMethod(bulgroz, "list", 1, 2);
286         result = jmethod.invoke(bulgroz, 1, 2);
287         assertEquals(4, result);
288         jmethod = uber.getMethod(bulgroz, "list", "1", bulgroz);
289         result = jmethod.invoke(bulgroz, "1", bulgroz);
290         assertEquals(5, result);
291         jmethod = uber.getMethod(bulgroz, "list", "1", "2");
292         result = jmethod.invoke(bulgroz, "1", "2");
293         assertEquals(6, result);
294         jmethod = uber.getMethod(bulgroz, "list", bulgroz, bulgroz);
295         result = jmethod.invoke(bulgroz, bulgroz, bulgroz);
296         assertEquals(8, result);
297         jmethod = uber.getMethod(bulgroz, "list", bulgroz, 1, bulgroz);
298         result = jmethod.invoke(bulgroz, bulgroz, 1, bulgroz);
299         assertEquals(7, result);
300         jmethod = uber.getMethod(bulgroz, "list", bulgroz, 1, "1");
301         result = jmethod.invoke(bulgroz, bulgroz, 1, "1");
302         assertEquals(7, result);
303         jmethod = uber.getMethod(bulgroz, "list", (Object) null);
304         result = jmethod.invoke(bulgroz,  (Object) null);
305         assertEquals(2, result);
306         jmethod = uber.getMethod(bulgroz, "list", bulgroz, (Object) null);
307         result = jmethod.invoke(bulgroz, bulgroz, (Object) null);
308         assertEquals(8, result);
309         jmethod = uber.getMethod(bulgroz, "list", null, "1");
310         result = jmethod.invoke(bulgroz, null, "1");
311         assertEquals(8, result);
312         jmethod = uber.getMethod(bulgroz, "list", bulgroz, null, null);
313         result = jmethod.invoke(bulgroz, bulgroz, null, null);
314         assertEquals(7, result);
315 
316         jmethod = uber.getMethod(bulgroz, "amb", 3d);
317         assertNotNull(jmethod);
318     }
319 }