View Javadoc
1   /*
2    *    Copyright 2009-2021 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      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      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      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      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      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      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      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      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     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 shouldGetAndSetNestedListItem() {
109     RichType rich = new RichType();
110     MetaObject meta = SystemMetaObject.forObject(rich);
111     meta.setValue("richType.richList[0]", "foo");
112     assertEquals("foo", meta.getValue("richType.richList[0]"));
113   }
114 
115   @Test
116   void shouldGetReadablePropertyNames() {
117     RichType rich = new RichType();
118     MetaObject meta = SystemMetaObject.forObject(rich);
119     String[] readables = meta.getGetterNames();
120     assertEquals(5, readables.length);
121     for (String readable : readables) {
122       assertTrue(meta.hasGetter(readable));
123       assertTrue(meta.hasGetter("richType." + readable));
124     }
125     assertTrue(meta.hasGetter("richType"));
126   }
127 
128   @Test
129   void shouldGetWriteablePropertyNames() {
130     RichType rich = new RichType();
131     MetaObject meta = SystemMetaObject.forObject(rich);
132     String[] writeables = meta.getSetterNames();
133     assertEquals(5, writeables.length);
134     for (String writeable : writeables) {
135       assertTrue(meta.hasSetter(writeable));
136       assertTrue(meta.hasSetter("richType." + writeable));
137     }
138     assertTrue(meta.hasSetter("richType"));
139   }
140 
141   @Test
142   void shouldSetPropertyOfNullNestedProperty() {
143     MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
144     richWithNull.setValue("richType.richProperty", "foo");
145     assertEquals("foo", richWithNull.getValue("richType.richProperty"));
146   }
147 
148   @Test
149   void shouldSetPropertyOfNullNestedPropertyWithNull() {
150     MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
151     richWithNull.setValue("richType.richProperty", null);
152     assertNull(richWithNull.getValue("richType.richProperty"));
153   }
154 
155   @Test
156   void shouldGetPropertyOfNullNestedProperty() {
157     MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
158     assertNull(richWithNull.getValue("richType.richProperty"));
159   }
160 
161   @Test
162   void shouldVerifyHasReadablePropertiesReturnedByGetReadablePropertyNames() {
163     MetaObject object = SystemMetaObject.forObject(new Author());
164     for (String readable : object.getGetterNames()) {
165       assertTrue(object.hasGetter(readable));
166     }
167   }
168 
169   @Test
170   void shouldVerifyHasWriteablePropertiesReturnedByGetWriteablePropertyNames() {
171     MetaObject object = SystemMetaObject.forObject(new Author());
172     for (String writeable : object.getSetterNames()) {
173       assertTrue(object.hasSetter(writeable));
174     }
175   }
176 
177   @Test
178   void shouldSetAndGetProperties() {
179     MetaObject object = SystemMetaObject.forObject(new Author());
180     object.setValue("email", "test");
181     assertEquals("test", object.getValue("email"));
182 
183   }
184 
185   @Test
186   void shouldVerifyPropertyTypes() {
187     MetaObject object = SystemMetaObject.forObject(new Author());
188     assertEquals(6, object.getSetterNames().length);
189     assertEquals(int.class, object.getGetterType("id"));
190     assertEquals(String.class, object.getGetterType("username"));
191     assertEquals(String.class, object.getGetterType("password"));
192     assertEquals(String.class, object.getGetterType("email"));
193     assertEquals(String.class, object.getGetterType("bio"));
194     assertEquals(Section.class, object.getGetterType("favouriteSection"));
195   }
196 
197   @Test
198   void shouldDemonstrateDeeplyNestedMapProperties() {
199     HashMap<String, String> map = new HashMap<>();
200     MetaObject metaMap = SystemMetaObject.forObject(map);
201 
202     assertTrue(metaMap.hasSetter("id"));
203     assertTrue(metaMap.hasSetter("name.first"));
204     assertTrue(metaMap.hasSetter("address.street"));
205 
206     assertFalse(metaMap.hasGetter("id"));
207     assertFalse(metaMap.hasGetter("name.first"));
208     assertFalse(metaMap.hasGetter("address.street"));
209 
210     metaMap.setValue("id", "100");
211     metaMap.setValue("name.first", "Clinton");
212     metaMap.setValue("name.last", "Begin");
213     metaMap.setValue("address.street", "1 Some Street");
214     metaMap.setValue("address.city", "This City");
215     metaMap.setValue("address.province", "A Province");
216     metaMap.setValue("address.postal_code", "1A3 4B6");
217 
218     assertTrue(metaMap.hasGetter("id"));
219     assertTrue(metaMap.hasGetter("name.first"));
220     assertTrue(metaMap.hasGetter("address.street"));
221 
222     assertEquals(3, metaMap.getGetterNames().length);
223     assertEquals(3, metaMap.getSetterNames().length);
224 
225     @SuppressWarnings("unchecked")
226     Map<String,String> name = (Map<String,String>) metaMap.getValue("name");
227     @SuppressWarnings("unchecked")
228     Map<String,String> address = (Map<String,String>) metaMap.getValue("address");
229 
230     assertEquals("Clinton", name.get("first"));
231     assertEquals("1 Some Street", address.get("street"));
232   }
233 
234   @Test
235   void shouldDemonstrateNullValueInMap() {
236     HashMap<String, String> map = new HashMap<>();
237     MetaObject metaMap = SystemMetaObject.forObject(map);
238     assertFalse(metaMap.hasGetter("phone.home"));
239 
240     metaMap.setValue("phone", null);
241     assertTrue(metaMap.hasGetter("phone"));
242     // hasGetter returns true if the parent exists and is null.
243     assertTrue(metaMap.hasGetter("phone.home"));
244     assertTrue(metaMap.hasGetter("phone.home.ext"));
245     assertNull(metaMap.getValue("phone"));
246     assertNull(metaMap.getValue("phone.home"));
247     assertNull(metaMap.getValue("phone.home.ext"));
248 
249     metaMap.setValue("phone.office", "789");
250     assertFalse(metaMap.hasGetter("phone.home"));
251     assertFalse(metaMap.hasGetter("phone.home.ext"));
252     assertEquals("789", metaMap.getValue("phone.office"));
253     assertNotNull(metaMap.getValue("phone"));
254     assertNull(metaMap.getValue("phone.home"));
255   }
256 
257   @Test
258   void shouldNotUseObjectWrapperFactoryByDefault() {
259     MetaObject meta = SystemMetaObject.forObject(new Author());
260     assertTrue(!meta.getObjectWrapper().getClass().equals(CustomBeanWrapper.class));
261   }
262 
263   @Test
264   void shouldUseObjectWrapperFactoryWhenSet() {
265     MetaObject meta = MetaObject.forObject(new Author(), SystemMetaObject.DEFAULT_OBJECT_FACTORY, new CustomBeanWrapperFactory(), new DefaultReflectorFactory());
266     assertEquals(CustomBeanWrapper.class, meta.getObjectWrapper().getClass());
267 
268     // Make sure the old default factory is in place and still works
269     meta = SystemMetaObject.forObject(new Author());
270     assertNotEquals(CustomBeanWrapper.class, meta.getObjectWrapper().getClass());
271   }
272 
273   @Test
274   void shouldMethodHasGetterReturnTrueWhenListElementSet() {
275     List<Object> param1 = new ArrayList<>();
276     param1.add("firstParam");
277     param1.add(222);
278     param1.add(new Date());
279 
280     Map<String, Object> parametersEmulation = new HashMap<>();
281     parametersEmulation.put("param1", param1);
282     parametersEmulation.put("filterParams", param1);
283 
284     MetaObject meta = SystemMetaObject.forObject(parametersEmulation);
285 
286     assertEquals(param1.get(0), meta.getValue("filterParams[0]"));
287     assertEquals(param1.get(1), meta.getValue("filterParams[1]"));
288     assertEquals(param1.get(2), meta.getValue("filterParams[2]"));
289 
290     assertTrue(meta.hasGetter("filterParams[0]"));
291     assertTrue(meta.hasGetter("filterParams[1]"));
292     assertTrue(meta.hasGetter("filterParams[2]"));
293   }
294 
295 }