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