View Javadoc

1   /*
2    * Copyright 2005,2009 Ivan SZKIBA
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.ini4j.spi;
17  
18  import org.ini4j.Ini4jCase;
19  
20  import org.ini4j.sample.Dwarf;
21  
22  import org.ini4j.test.Helper;
23  
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertFalse;
26  import static org.junit.Assert.assertNotNull;
27  import static org.junit.Assert.assertNull;
28  import static org.junit.Assert.assertSame;
29  import static org.junit.Assert.assertTrue;
30  import static org.junit.Assert.fail;
31  
32  import org.junit.Test;
33  
34  import java.beans.PropertyChangeEvent;
35  import java.beans.PropertyChangeListener;
36  import java.beans.PropertyVetoException;
37  import java.beans.VetoableChangeListener;
38  
39  import java.lang.reflect.Proxy;
40  
41  import java.util.HashMap;
42  import java.util.Map;
43  
44  public class AbstractBeanInvocationHandlerTest extends Ini4jCase
45  {
46      private static final String PROP_AGE = Dwarf.PROP_AGE;
47      private static final String PROP_HEIGHT = Dwarf.PROP_HEIGHT;
48  
49      @Test public void testGetProperty() throws Exception
50      {
51          Map<String, String> map = new HashMap<String, String>();
52          MapBeanHandler handler = new MapBeanHandler(map);
53          Integer i = new Integer(23);
54  
55          map.put(PROP_AGE, "23");
56          assertEquals(i, (Integer) handler.getProperty(PROP_AGE, Integer.class));
57          assertTrue(handler.hasProperty(PROP_AGE));
58          assertFalse(handler.hasProperty(null));
59          map.put(PROP_AGE, "?.");
60          assertEquals(null, handler.getProperty(PROP_AGE, Integer.class));
61          assertEquals("?.", (String) handler.getProperty(PROP_AGE, String.class));
62          handler = new MapBeanHandler(map)
63          {
64              @Override protected boolean hasPropertySpi(String property)
65              {
66                  throw new UnsupportedOperationException();
67              }
68          };
69          assertFalse(handler.hasProperty(PROP_AGE));
70      }
71  
72      @Test public void testGetSetHas() throws Exception
73      {
74          Dwarf dwarf = MapBeanHandler.newBean(Dwarf.class);
75  
76          assertFalse(dwarf.hasAge());
77          dwarf.setAge(23);
78          assertEquals(23, dwarf.getAge());
79          assertNull(dwarf.getHomeDir());
80          dwarf.setHomeDir("dummy");
81      }
82  
83      @Test public void testMisc() throws Exception
84      {
85          Map<String, String> map = new HashMap<String, String>();
86          MapBeanHandler handler = new MapBeanHandler(map);
87          Dummy dummy = (Dummy) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Dummy.class }, handler);
88  
89          assertNull(handler.getProxy());
90  
91          // non existend method calls
92          dummy.dummy();
93          dummy.addDummy();
94          dummy.removeDummy();
95  
96          // boolean invoke
97          map.put("dummy", "true");
98          assertTrue(dummy.isDummy());
99          assertSame(dummy, handler.getProxy());
100 
101         // subclass should call fire methods any time
102         // so null support reference should be not a problem
103         handler.firePropertyChange(PROP_AGE, Integer.valueOf(1), Integer.valueOf(2));
104         handler.fireVetoableChange(PROP_AGE, Integer.valueOf(1), Integer.valueOf(2));
105     }
106 
107     @Test public void testPropertyChangeListener() throws Exception
108     {
109         class Listener implements PropertyChangeListener
110         {
111             int _counter;
112             String _property;
113             PropertyChangeEvent _event;
114 
115             Listener(String property)
116             {
117                 _property = property;
118             }
119 
120             @Override public void propertyChange(PropertyChangeEvent event)
121             {
122                 if (_property.equals(event.getPropertyName()))
123                 {
124                     _counter++;
125                     _event = event;
126                 }
127             }
128         }
129 
130         Dwarf d = MapBeanHandler.newBean(Dwarf.class);
131         Listener l = new Listener(PROP_AGE);
132 
133         // test add and remove: invalid state should be OK
134         d.removePropertyChangeListener(PROP_AGE, l);
135         d.addPropertyChangeListener(PROP_AGE, l);
136         d.addPropertyChangeListener(PROP_AGE, l);
137         d.removePropertyChangeListener(PROP_AGE, l);
138         d.removePropertyChangeListener(PROP_AGE, l);
139 
140         // check listener call
141         d.setAge(23);
142         d.addPropertyChangeListener(PROP_AGE, l);
143         d.setAge(45);
144         assertNotNull(l._event);
145         assertEquals(23, ((Integer) l._event.getOldValue()).intValue());
146         assertEquals(45, ((Integer) l._event.getNewValue()).intValue());
147 
148         // check listener call again
149         d.setAge(2);
150         d.setWeight(23.4);
151         assertEquals(2, l._counter);
152         d.removePropertyChangeListener(PROP_AGE, l);
153 
154         // should not run listener
155         d.setAge(44);
156         assertEquals(2, l._counter);
157 
158         // test remove listener> invalid state should be OK
159         d.removePropertyChangeListener(PROP_AGE, l);
160     }
161 
162     @Test public void testSetProperty() throws Exception
163     {
164         Map<String, String> map = new HashMap<String, String>();
165         MapBeanHandler handler = new MapBeanHandler(map);
166 
167         // very special case: set string property to non stirng value implies string conversion
168         handler.setProperty(PROP_AGE, new Integer(23), String.class);
169         assertEquals("23", handler.getProperty(PROP_AGE, String.class));
170     }
171 
172     @Test public void testVetoableChangeListener() throws Exception
173     {
174         class HeightCheck implements VetoableChangeListener
175         {
176             @Override public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException
177             {
178                 if (PROP_HEIGHT.equals(event.getPropertyName()))
179                 {
180                     if (((Double) event.getNewValue()) < 0.0)
181                     {
182                         throw new PropertyVetoException("invalid value", event);
183                     }
184                 }
185             }
186         }
187 
188         Dwarf d = MapBeanHandler.newBean(Dwarf.class);
189         HeightCheck l = new HeightCheck();
190 
191         // test add and remove: invalid state should be OK
192         d.removeVetoableChangeListener(PROP_HEIGHT, l);
193         d.addVetoableChangeListener(PROP_HEIGHT, l);
194         d.addVetoableChangeListener(PROP_HEIGHT, l);
195         d.removeVetoableChangeListener(PROP_HEIGHT, l);
196         d.removeVetoableChangeListener(PROP_HEIGHT, l);
197 
198         // set invalid value without lsitener
199         d.setHeight(-2.0);
200         d.setHeight(33.0);
201         d.addVetoableChangeListener(PROP_HEIGHT, l);
202 
203         // set invalid value with listener
204         try
205         {
206             d.setHeight(-3.4);
207             fail();
208         }
209         catch (PropertyVetoException x)
210         {
211             assertEquals(33.0, d.getHeight(), Helper.DELTA);
212         }
213 
214         // set valid value
215         d.setHeight(44.0);
216         assertEquals(44.0, d.getHeight(), Helper.DELTA);
217         d.removeVetoableChangeListener(PROP_HEIGHT, l);
218 
219         // set invalid value without lsitener
220         d.setHeight(-4.0);
221         assertEquals(-4.0, d.getHeight(), Helper.DELTA);
222 
223         // test remove: invalid state should be OK
224         d.removeVetoableChangeListener(PROP_HEIGHT, l);
225     }
226 
227     static interface Dummy
228     {
229         boolean isDummy();
230 
231         void addDummy();
232 
233         void dummy();
234 
235         void removeDummy();
236     }
237 
238     static class MapBeanHandler extends AbstractBeanInvocationHandler
239     {
240         private Map<String, String> _map;
241 
242         MapBeanHandler(Map<String, String> map)
243         {
244             super();
245             _map = map;
246         }
247 
248         protected static <T> T newBean(Class<T> clazz)
249         {
250             return newBean(clazz, new HashMap<String, String>());
251         }
252 
253         protected static <T> T newBean(Class<T> clazz, Map<String, String> map)
254         {
255             return clazz.cast(Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, new MapBeanHandler(map)));
256         }
257 
258         @Override protected Object getPropertySpi(String property, Class clazz)
259         {
260             return _map.get(property);
261         }
262 
263         @Override protected void setPropertySpi(String property, Object value, Class clazz)
264         {
265             _map.put(property, value.toString());
266         }
267 
268         @Override protected boolean hasPropertySpi(String property)
269         {
270             return _map.containsKey(property);
271         }
272     }
273 }