View Javadoc
1   /**
2    *    Copyright 2009-2020 the original author or authors.
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.ibatis.reflection;
17  
18  import static org.junit.jupiter.api.Assertions.*;
19  
20  import java.util.ArrayList;
21  import java.util.Date;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.ibatis.domain.blog.Author;
27  import org.apache.ibatis.domain.blog.Section;
28  import org.apache.ibatis.domain.misc.CustomBeanWrapper;
29  import org.apache.ibatis.domain.misc.CustomBeanWrapperFactory;
30  import org.apache.ibatis.domain.misc.RichType;
31  import org.junit.jupiter.api.Test;
32  
33  class MetaObjectTest {
34  
35    @Test
36    void shouldGetAndSetField() {
37      RichTypec/RichType.html#RichType">RichType rich = new RichType();
38      MetaObject meta = SystemMetaObject.forObject(rich);
39      meta.setValue("richField", "foo");
40      assertEquals("foo", meta.getValue("richField"));
41    }
42  
43    @Test
44    void shouldGetAndSetNestedField() {
45      RichTypec/RichType.html#RichType">RichType rich = new RichType();
46      MetaObject meta = SystemMetaObject.forObject(rich);
47      meta.setValue("richType.richField", "foo");
48      assertEquals("foo", meta.getValue("richType.richField"));
49    }
50  
51    @Test
52    void shouldGetAndSetProperty() {
53      RichTypec/RichType.html#RichType">RichType rich = new RichType();
54      MetaObject meta = SystemMetaObject.forObject(rich);
55      meta.setValue("richProperty", "foo");
56      assertEquals("foo", meta.getValue("richProperty"));
57    }
58  
59    @Test
60    void shouldGetAndSetNestedProperty() {
61      RichTypec/RichType.html#RichType">RichType rich = new RichType();
62      MetaObject meta = SystemMetaObject.forObject(rich);
63      meta.setValue("richType.richProperty", "foo");
64      assertEquals("foo", meta.getValue("richType.richProperty"));
65    }
66  
67    @Test
68    void shouldGetAndSetMapPair() {
69      RichTypec/RichType.html#RichType">RichType rich = new RichType();
70      MetaObject meta = SystemMetaObject.forObject(rich);
71      meta.setValue("richMap.key", "foo");
72      assertEquals("foo", meta.getValue("richMap.key"));
73    }
74  
75    @Test
76    void shouldGetAndSetMapPairUsingArraySyntax() {
77      RichTypec/RichType.html#RichType">RichType rich = new RichType();
78      MetaObject meta = SystemMetaObject.forObject(rich);
79      meta.setValue("richMap[key]", "foo");
80      assertEquals("foo", meta.getValue("richMap[key]"));
81    }
82  
83    @Test
84    void shouldGetAndSetNestedMapPair() {
85      RichTypec/RichType.html#RichType">RichType rich = new RichType();
86      MetaObject meta = SystemMetaObject.forObject(rich);
87      meta.setValue("richType.richMap.key", "foo");
88      assertEquals("foo", meta.getValue("richType.richMap.key"));
89    }
90  
91    @Test
92    void shouldGetAndSetNestedMapPairUsingArraySyntax() {
93      RichTypec/RichType.html#RichType">RichType rich = new RichType();
94      MetaObject meta = SystemMetaObject.forObject(rich);
95      meta.setValue("richType.richMap[key]", "foo");
96      assertEquals("foo", meta.getValue("richType.richMap[key]"));
97    }
98  
99    @Test
100   void shouldGetAndSetListItem() {
101     RichTypec/RichType.html#RichType">RichType rich = new RichType();
102     MetaObject meta = SystemMetaObject.forObject(rich);
103     meta.setValue("richList[0]", "foo");
104     assertEquals("foo", meta.getValue("richList[0]"));
105   }
106 
107   @Test
108   void shouldSetAndGetSelfListItem() {
109     RichTypec/RichType.html#RichType">RichType rich = new RichType();
110     MetaObject meta = SystemMetaObject.forObject(rich);
111     meta.setValue("richList[0]", "foo");
112     assertEquals("foo", meta.getValue("richList[0]"));
113   }
114 
115   @Test
116   void shouldGetAndSetNestedListItem() {
117     RichTypec/RichType.html#RichType">RichType rich = new RichType();
118     MetaObject meta = SystemMetaObject.forObject(rich);
119     meta.setValue("richType.richList[0]", "foo");
120     assertEquals("foo", meta.getValue("richType.richList[0]"));
121   }
122 
123   @Test
124   void shouldGetReadablePropertyNames() {
125     RichTypec/RichType.html#RichType">RichType rich = new RichType();
126     MetaObject meta = SystemMetaObject.forObject(rich);
127     String[] readables = meta.getGetterNames();
128     assertEquals(5, readables.length);
129     for (String readable : readables) {
130       assertTrue(meta.hasGetter(readable));
131       assertTrue(meta.hasGetter("richType." + readable));
132     }
133     assertTrue(meta.hasGetter("richType"));
134   }
135 
136   @Test
137   void shouldGetWriteablePropertyNames() {
138     RichTypec/RichType.html#RichType">RichType rich = new RichType();
139     MetaObject meta = SystemMetaObject.forObject(rich);
140     String[] writeables = meta.getSetterNames();
141     assertEquals(5, writeables.length);
142     for (String writeable : writeables) {
143       assertTrue(meta.hasSetter(writeable));
144       assertTrue(meta.hasSetter("richType." + writeable));
145     }
146     assertTrue(meta.hasSetter("richType"));
147   }
148 
149   @Test
150   void shouldSetPropertyOfNullNestedProperty() {
151     MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
152     richWithNull.setValue("richType.richProperty", "foo");
153     assertEquals("foo", richWithNull.getValue("richType.richProperty"));
154   }
155 
156   @Test
157   void shouldSetPropertyOfNullNestedPropertyWithNull() {
158     MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
159     richWithNull.setValue("richType.richProperty", null);
160     assertNull(richWithNull.getValue("richType.richProperty"));
161   }
162 
163   @Test
164   void shouldGetPropertyOfNullNestedProperty() {
165     MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
166     assertNull(richWithNull.getValue("richType.richProperty"));
167   }
168 
169   @Test
170   void shouldVerifyHasReadablePropertiesReturnedByGetReadablePropertyNames() {
171     MetaObject object = SystemMetaObject.forObject(new Author());
172     for (String readable : object.getGetterNames()) {
173       assertTrue(object.hasGetter(readable));
174     }
175   }
176 
177   @Test
178   void shouldVerifyHasWriteablePropertiesReturnedByGetWriteablePropertyNames() {
179     MetaObject object = SystemMetaObject.forObject(new Author());
180     for (String writeable : object.getSetterNames()) {
181       assertTrue(object.hasSetter(writeable));
182     }
183   }
184 
185   @Test
186   void shouldSetAndGetProperties() {
187     MetaObject object = SystemMetaObject.forObject(new Author());
188     object.setValue("email", "test");
189     assertEquals("test", object.getValue("email"));
190 
191   }
192 
193   @Test
194   void shouldVerifyPropertyTypes() {
195     MetaObject object = SystemMetaObject.forObject(new Author());
196     assertEquals(6, object.getSetterNames().length);
197     assertEquals(int.class, object.getGetterType("id"));
198     assertEquals(String.class, object.getGetterType("username"));
199     assertEquals(String.class, object.getGetterType("password"));
200     assertEquals(String.class, object.getGetterType("email"));
201     assertEquals(String.class, object.getGetterType("bio"));
202     assertEquals(Section.class, object.getGetterType("favouriteSection"));
203   }
204 
205   @Test
206   void shouldDemonstrateDeeplyNestedMapProperties() {
207     HashMap<String, String> map = new HashMap<>();
208     MetaObject metaMap = SystemMetaObject.forObject(map);
209 
210     assertTrue(metaMap.hasSetter("id"));
211     assertTrue(metaMap.hasSetter("name.first"));
212     assertTrue(metaMap.hasSetter("address.street"));
213 
214     assertFalse(metaMap.hasGetter("id"));
215     assertFalse(metaMap.hasGetter("name.first"));
216     assertFalse(metaMap.hasGetter("address.street"));
217 
218     metaMap.setValue("id", "100");
219     metaMap.setValue("name.first", "Clinton");
220     metaMap.setValue("name.last", "Begin");
221     metaMap.setValue("address.street", "1 Some Street");
222     metaMap.setValue("address.city", "This City");
223     metaMap.setValue("address.province", "A Province");
224     metaMap.setValue("address.postal_code", "1A3 4B6");
225 
226     assertTrue(metaMap.hasGetter("id"));
227     assertTrue(metaMap.hasGetter("name.first"));
228     assertTrue(metaMap.hasGetter("address.street"));
229 
230     assertEquals(3, metaMap.getGetterNames().length);
231     assertEquals(3, metaMap.getSetterNames().length);
232 
233     @SuppressWarnings("unchecked")
234     Map<String,String> name = (Map<String,String>) metaMap.getValue("name");
235     @SuppressWarnings("unchecked")
236     Map<String,String> address = (Map<String,String>) metaMap.getValue("address");
237 
238     assertEquals("Clinton", name.get("first"));
239     assertEquals("1 Some Street", address.get("street"));
240   }
241 
242   @Test
243   void shouldDemonstrateNullValueInMap() {
244     HashMap<String, String> map = new HashMap<>();
245     MetaObject metaMap = SystemMetaObject.forObject(map);
246     assertFalse(metaMap.hasGetter("phone.home"));
247 
248     metaMap.setValue("phone", null);
249     assertTrue(metaMap.hasGetter("phone"));
250     // hasGetter returns true if the parent exists and is null.
251     assertTrue(metaMap.hasGetter("phone.home"));
252     assertTrue(metaMap.hasGetter("phone.home.ext"));
253     assertNull(metaMap.getValue("phone"));
254     assertNull(metaMap.getValue("phone.home"));
255     assertNull(metaMap.getValue("phone.home.ext"));
256 
257     metaMap.setValue("phone.office", "789");
258     assertFalse(metaMap.hasGetter("phone.home"));
259     assertFalse(metaMap.hasGetter("phone.home.ext"));
260     assertEquals("789", metaMap.getValue("phone.office"));
261     assertNotNull(metaMap.getValue("phone"));
262     assertNull(metaMap.getValue("phone.home"));
263   }
264 
265   @Test
266   void shouldNotUseObjectWrapperFactoryByDefault() {
267     MetaObject meta = SystemMetaObject.forObject(new Author());
268     assertTrue(!meta.getObjectWrapper().getClass().equals(CustomBeanWrapper.class));
269   }
270 
271   @Test
272   void shouldUseObjectWrapperFactoryWhenSet() {
273     MetaObject meta = MetaObject.forObject(new Author(), SystemMetaObject.DEFAULT_OBJECT_FACTORY, new CustomBeanWrapperFactory(), new DefaultReflectorFactory());
274     assertEquals(CustomBeanWrapper.class, meta.getObjectWrapper().getClass());
275 
276     // Make sure the old default factory is in place and still works
277     meta = SystemMetaObject.forObject(new Author());
278     assertNotEquals(CustomBeanWrapper.class, meta.getObjectWrapper().getClass());
279   }
280 
281   @Test
282   void shouldMethodHasGetterReturnTrueWhenListElementSet() {
283     List<Object> param1 = new ArrayList<>();
284     param1.add("firstParam");
285     param1.add(222);
286     param1.add(new Date());
287 
288     Map<String, Object> parametersEmulation = new HashMap<>();
289     parametersEmulation.put("param1", param1);
290     parametersEmulation.put("filterParams", param1);
291 
292     MetaObject meta = SystemMetaObject.forObject(parametersEmulation);
293 
294     assertEquals(param1.get(0), meta.getValue("filterParams[0]"));
295     assertEquals(param1.get(1), meta.getValue("filterParams[1]"));
296     assertEquals(param1.get(2), meta.getValue("filterParams[2]"));
297 
298     assertTrue(meta.hasGetter("filterParams[0]"));
299     assertTrue(meta.hasGetter("filterParams[1]"));
300     assertTrue(meta.hasGetter("filterParams[2]"));
301   }
302 
303 }