1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.binding.value.support;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Random;
26 import java.util.Set;
27 import java.util.SortedSet;
28 import java.util.TreeSet;
29
30 import org.springframework.beans.BeanUtils;
31 import org.springframework.binding.support.TestPropertyChangeListener;
32 import org.springframework.binding.value.CommitTrigger;
33 import org.springframework.binding.value.ValueModel;
34 import org.springframework.richclient.test.SpringRichTestCase;
35
36
37
38
39
40
41 public class BufferedCollectionValueModelTests extends SpringRichTestCase {
42
43 private Class[] supportedIterfaces = new Class[] {Collection.class, List.class, Set.class, SortedSet.class,};
44
45 private Class[] supportedClasses = new Class[] {ArrayList.class, HashSet.class, TreeSet.class,};
46
47 public void testCreating() {
48 try {
49 getBufferedCollectionValueModel(null, null);
50 fail("NULL wrappedType should not be supported");
51 }
52 catch (IllegalArgumentException e) {
53
54 }
55 try {
56 getBufferedCollectionValueModel(null, Object.class);
57 fail("wrappedType can only be an instance Collection or an array");
58 }
59 catch (IllegalArgumentException e) {
60
61 }
62 try {
63 getBufferedCollectionValueModel(null, int[].class);
64 fail("wrappedType can not be a primitive array");
65 }
66 catch (IllegalArgumentException e) {
67
68 }
69 for (int i = 0; i < supportedIterfaces.length; i++) {
70 getBufferedCollectionValueModel(null, supportedIterfaces[i]);
71 }
72 try {
73 getBufferedCollectionValueModel(null, CustomCollectionInterface.class);
74 fail("if wrappedType is an interface it must one of the standard JDK Collection interfaces");
75 }
76 catch (IllegalArgumentException e) {
77
78 }
79 getBufferedCollectionValueModel(null, Object[].class);
80 getBufferedCollectionValueModel(null, CustomCollectionClass.class);
81 for (int i = 0; i < supportedClasses.length; i++) {
82 getBufferedCollectionValueModel(null, supportedClasses[i]);
83 }
84 }
85
86 public void testGetAfterBackingObjectChange() {
87 Object[] backingArray = getArray(1);
88 BufferedCollectionValueModel vm = getBufferedCollectionValueModel(backingArray);
89 assertHasSameStructure((ListListModel)vm.getValue(), backingArray);
90
91 backingArray = getArray(2);
92 vm.getWrappedValueModel().setValue(backingArray);
93 assertHasSameStructure((ListListModel)vm.getValue(), backingArray);
94
95 vm.getWrappedValueModel().setValue(null);
96 assertEquals("ListListModel must have no elements when backing collection is NULL",
97 ((ListListModel)vm.getValue()).size(), 0);
98
99 for (int i = 0; i < supportedClasses.length; i++) {
100 Collection backingCollection = getCollection(supportedClasses[i], i);
101 vm = getBufferedCollectionValueModel(backingCollection);
102 assertHasSameStructure((ListListModel)vm.getValue(), backingCollection);
103
104 backingCollection = getCollection(supportedClasses[i], i + 1);
105 vm.getWrappedValueModel().setValue(backingCollection);
106 assertHasSameStructure((ListListModel)vm.getValue(), backingCollection);
107
108 vm.getWrappedValueModel().setValue(null);
109 assertEquals("ListListModel must have no elements when backing collection is NULL",
110 ((ListListModel)vm.getValue()).size(), 0);
111 }
112 }
113
114 public void testCreateWithEmptyCollection() {
115 BufferedCollectionValueModel vm = new BufferedCollectionValueModel(new ValueHolder(null), Collection.class);
116 assertTrue(vm.getValue() instanceof ListListModel);
117 assertEquals(0, ((ListListModel)vm.getValue()).size());
118
119 vm = new BufferedCollectionValueModel(new ValueHolder(new ArrayList()), Collection.class);
120 assertTrue(vm.getValue() instanceof ListListModel);
121 assertEquals(0, ((ListListModel)vm.getValue()).size());
122
123 vm = new BufferedCollectionValueModel(new ValueHolder(null), Object[].class);
124 assertTrue(vm.getValue() instanceof ListListModel);
125 assertEquals(0, ((ListListModel)vm.getValue()).size());
126
127 vm = new BufferedCollectionValueModel(new ValueHolder(new Object[0]), Object[].class);
128 assertTrue(vm.getValue() instanceof ListListModel);
129 assertEquals(0, ((ListListModel)vm.getValue()).size());
130 }
131
132 public void testChangesToListListModelWithBackingArray() {
133 Object[] backingArray = getArray(100);
134 BufferedCollectionValueModel vm = getBufferedCollectionValueModel(backingArray);
135 ListListModel llm = (ListListModel)vm.getValue();
136 llm.clear();
137 assertEquals("changes to ListListModel should be not be made to backing array unless commit is called",
138 vm.getWrappedValueModel().getValue(), backingArray);
139
140 backingArray = getArray(101);
141 vm.getWrappedValueModel().setValue(backingArray);
142 Object newValue = new Double(1);
143 llm.set(1, newValue);
144 vm.commit();
145 Object[] newBackingArray = (Object[])vm.getWrappedValueModel().getValue();
146 assertNotSame("change should not have been committed back to original array", newBackingArray, backingArray);
147
148 llm.add(newValue);
149 vm.commit();
150 newBackingArray = (Object[])vm.getWrappedValueModel().getValue();
151 assertNotSame("change should not have been committed back to original array", newBackingArray, backingArray);
152 assertTrue(newBackingArray.length == backingArray.length + 1);
153 assertEquals(newBackingArray[newBackingArray.length - 1], newValue);
154
155 llm.clear();
156 vm.commit();
157 newBackingArray = (Object[])vm.getWrappedValueModel().getValue();
158 assertEquals(newBackingArray.length, 0);
159
160 vm.getWrappedValueModel().setValue(null);
161 llm.clear();
162 vm.commit();
163 assertEquals("if backingCollection is NULL then a commit of an empty LLM should also be NULL",
164 vm.getWrappedValueModel().getValue(), null);
165
166 llm.add(newValue);
167 vm.commit();
168 newBackingArray = (Object[])vm.getWrappedValueModel().getValue();
169 assertEquals(newBackingArray.length, 1);
170 assertEquals(newBackingArray[0], newValue);
171 }
172
173 public void testChangesToListListModelWithBackingCollection() {
174 for (int i = 0; i < supportedClasses.length; i++) {
175 Collection backingCollection = getCollection(supportedClasses[i], 200 + i);
176 BufferedCollectionValueModel vm = getBufferedCollectionValueModel(backingCollection);
177 ListListModel llm = (ListListModel)vm.getValue();
178 llm.clear();
179 assertEquals("changes to LLM should be not be made to backing collection unless commit is called",
180 vm.getWrappedValueModel().getValue(), backingCollection);
181
182 backingCollection = getCollection(supportedClasses[i], 201 + i);
183 vm.getWrappedValueModel().setValue(backingCollection);
184 Object newValue = new Integer(-1);
185 backingCollection.remove(newValue);
186 int orgSize = backingCollection.size();
187 llm.set(1, newValue);
188 vm.commit();
189 Collection newBackingCollection = (Collection)vm.getWrappedValueModel().getValue();
190 assertTrue("change should not have been committed back to original array",
191 !backingCollection.contains(newValue));
192 assertTrue(newBackingCollection.contains(newValue));
193 assertTrue(orgSize == newBackingCollection.size());
194
195 newValue = new Integer(-2);
196 backingCollection.remove(newValue);
197 orgSize = backingCollection.size();
198 llm.add(newValue);
199 vm.commit();
200 newBackingCollection = (Collection)vm.getWrappedValueModel().getValue();
201
202 assertTrue(newBackingCollection.contains(newValue));
203 assertTrue(newBackingCollection.size() == orgSize + 1);
204
205 llm.clear();
206 vm.commit();
207 assertEquals(((Collection)vm.getWrappedValueModel().getValue()).size(), 0);
208
209 vm.getWrappedValueModel().setValue(null);
210 llm.clear();
211 vm.commit();
212 newBackingCollection = (Collection)vm.getWrappedValueModel().getValue();
213 assertEquals("if backingCollection is NULL then a commit of an empty LLM should also be NULL",
214 newBackingCollection, null);
215
216 llm.add(newValue);
217 vm.commit();
218 newBackingCollection = (Collection)vm.getWrappedValueModel().getValue();
219 assertTrue(supportedClasses[i].isAssignableFrom(newBackingCollection.getClass()));
220 assertEquals(newBackingCollection.size(), 1);
221 assertEquals(newBackingCollection.iterator().next(), newValue);
222 }
223 }
224
225 public void testListListModelKeepsStuctureOfBackingObjectAfterCommit() {
226 Collection backingCollection = getCollection(HashSet.class, 500);
227 int origLength = backingCollection.size();
228 BufferedCollectionValueModel vm = getBufferedCollectionValueModel(backingCollection);
229 ListListModel llm = (ListListModel)vm.getValue();
230 llm.add(backingCollection.iterator().next());
231 assertTrue(llm.size() == origLength + 1);
232 vm.commit();
233 assertTrue("adding a duplicate item should not change the size of a set", llm.size() == origLength);
234 assertHasSameStructure(llm, backingCollection);
235
236 backingCollection = getCollection(TreeSet.class, 501);
237 vm = getBufferedCollectionValueModel(backingCollection);
238 llm = (ListListModel)vm.getValue();
239 Collections.reverse(llm);
240 assertTrue(((Comparable)llm.get(0)).compareTo(llm.get(1)) > 0);
241 vm.commit();
242 assertTrue("LLM should be sorted the same way as backingCollection",
243 ((Comparable)llm.get(0)).compareTo(llm.get(1)) < 0);
244 assertHasSameStructure(llm, backingCollection);
245
246 backingCollection = new TreeSet(new Comparator() {
247
248 public int compare(Object o1, Object o2) {
249 return ((Comparable)o2).compareTo(o1);
250 }
251
252 });
253 populateCollection(backingCollection, 502);
254 vm = getBufferedCollectionValueModel(backingCollection);
255 llm = (ListListModel)vm.getValue();
256 Collections.reverse(llm);
257 assertTrue(((Comparable)llm.get(0)).compareTo(llm.get(1)) < 0);
258 vm.commit();
259 assertTrue("LLM should be sorted the same way as backingCollection",
260 ((Comparable)llm.get(0)).compareTo(llm.get(1)) > 0);
261 assertHasSameStructure(llm, backingCollection);
262 }
263
264 public void testIncompatibleCollections() {
265 try {
266 getBufferedCollectionValueModel(new ArrayList(), Set.class);
267 fail("backing object must be assignable to backingCollectionClass");
268 }
269 catch (IllegalArgumentException e) {
270
271 }
272 try {
273 getBufferedCollectionValueModel(new Double[0], Integer[].class);
274 fail("backing object must be assignable to backingCollectionClass");
275 }
276 catch (IllegalArgumentException e) {
277
278 }
279 }
280
281 public void testValueChangeNotification() {
282 Object[] backingArray = getArray(100);
283 BufferedCollectionValueModel vm = getBufferedCollectionValueModel(backingArray);
284 TestPropertyChangeListener vl = new TestPropertyChangeListener(ValueModel.VALUE_PROPERTY);
285 vm.addValueChangeListener(vl);
286
287 ListListModel llm = (ListListModel)vm.getValue();
288 assertEquals(0, vl.eventCount());
289
290 vl.reset();
291 llm.add(new Integer(100));
292 assertEquals(1, vl.eventCount());
293 llm.add(1, new Integer(102));
294 assertEquals(2, vl.eventCount());
295
296 vl.reset();
297 llm.addAll(getCollection(ArrayList.class, 101));
298 assertEquals(1, vl.eventCount());
299 llm.addAll(1, getCollection(ArrayList.class, 101));
300 assertEquals(2, vl.eventCount());
301
302 vl.reset();
303 llm.remove(1);
304 assertEquals(1, vl.eventCount());
305 llm.removeAll(getCollection(ArrayList.class, 101));
306 assertEquals(2, vl.eventCount());
307
308 vl.reset();
309 llm.set(1, llm.get(1));
310 assertEquals(0, vl.eventCount());
311
312 vl.reset();
313 llm.clear();
314 assertEquals(1, vl.eventCount());
315 }
316
317 public void testRevert() {
318 CommitTrigger commitTriger = new CommitTrigger();
319
320 Collection backingCollection = getCollection(HashSet.class, 700);
321 BufferedCollectionValueModel vm = getBufferedCollectionValueModel(backingCollection);
322 vm.setCommitTrigger(commitTriger);
323 ListListModel llm = (ListListModel)vm.getValue();
324 llm.clear();
325 commitTriger.revert();
326 assertHasSameStructure(llm, backingCollection);
327 }
328
329 private void assertHasSameStructure(ListListModel c1, Object[] c2) {
330 assertEquals("collections must be the same size", c1.size(), c2.length);
331 for (int i = 0; i < c2.length; i++) {
332 assertEquals("collections must have the same items in the same order", c1.get(i), c2[i]);
333 }
334 }
335
336 private void assertHasSameStructure(ListListModel c1, Collection c2) {
337 assertEquals("collections must be the same size", c2.size(), c1.size());
338 for (Iterator i = c1.iterator(), j = c2.iterator(); i.hasNext();) {
339 assertEquals("collections must have the same items in the same order", i.next(), j.next());
340 }
341 }
342
343 private Object[] getArray(long randomSeed) {
344 Random random = new Random(randomSeed);
345 return new Number[] {new Integer(random.nextInt()), new Integer(random.nextInt()),
346 new Integer(random.nextInt())};
347 }
348
349 private Collection getCollection(Class collectionClass, long randomSeed) {
350 return populateCollection((Collection)BeanUtils.instantiateClass(collectionClass), randomSeed);
351 }
352
353 private Collection populateCollection(Collection c, long randomSeed) {
354 Random random = new Random(randomSeed);
355 c.add(new Integer(random.nextInt()));
356 c.add(new Integer(random.nextInt()));
357 c.add(new Integer(random.nextInt()));
358 return c;
359 }
360
361 private BufferedCollectionValueModel getBufferedCollectionValueModel(Object backingCollecton) {
362 return getBufferedCollectionValueModel(backingCollecton, backingCollecton.getClass());
363 }
364
365 private BufferedCollectionValueModel getBufferedCollectionValueModel(Object backingCollecton,
366 Class backingCollectionClass) {
367 ValueModel vm = new ValueHolder(backingCollecton);
368 return new BufferedCollectionValueModel(vm, backingCollectionClass);
369 }
370
371 interface CustomCollectionInterface extends Collection {
372
373 }
374
375 class CustomCollectionClass extends ArrayList implements CustomCollectionInterface {
376
377 }
378 }