comparison org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableList.d @ 95:6208d4f6a277

Added trees for databinding.beans and observable
author Frank Benoit <benoit@tionex.de>
date Tue, 21 Apr 2009 10:55:51 +0200
parents
children b74ac5dfcc06
comparison
equal deleted inserted replaced
94:1d37a7813832 95:6208d4f6a277
1 /*******************************************************************************
2 * Copyright (c) 2006-2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Brad Reynolds - bug 171616
11 * Matthew Hall - bugs 208858, 221351, 213145, 223164, 244098
12 * Mike Evans - bug 217558
13 *******************************************************************************/
14
15 package org.eclipse.core.internal.databinding.beans;
16
17 import java.beans.PropertyChangeListener;
18 import java.beans.PropertyDescriptor;
19 import java.lang.reflect.Array;
20 import java.lang.reflect.InvocationTargetException;
21 import java.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.Iterator;
26 import java.util.List;
27
28 import org.eclipse.core.databinding.BindingException;
29 import org.eclipse.core.databinding.beans.IBeanObservable;
30 import org.eclipse.core.databinding.observable.Diffs;
31 import org.eclipse.core.databinding.observable.Realm;
32 import org.eclipse.core.databinding.observable.list.ListDiffEntry;
33 import org.eclipse.core.databinding.observable.list.ObservableList;
34
35 /**
36 * @since 1.0
37 *
38 */
39 public class JavaBeanObservableList : ObservableList ,
40 IBeanObservable {
41
42 private final Object object;
43
44 private bool updating = false;
45
46 private PropertyDescriptor descriptor;
47
48 private ListenerSupport listenerSupport;
49
50 /**
51 * @param realm
52 * @param object
53 * @param descriptor
54 * @param elementType
55 */
56 public this(Realm realm, Object object,
57 PropertyDescriptor descriptor, Class elementType) {
58 this(realm, object, descriptor, elementType, true);
59 }
60
61 /**
62 * @param realm
63 * @param object
64 * @param descriptor
65 * @param elementType
66 * @param attachListeners
67 */
68 public this(Realm realm, Object object,
69 PropertyDescriptor descriptor, Class elementType,
70 bool attachListeners) {
71
72 super(realm, new ArrayList(), elementType);
73 this.object = object;
74 this.descriptor = descriptor;
75
76 if (attachListeners) {
77 PropertyChangeListener listener = new class() PropertyChangeListener {
78 public void propertyChange(java.beans.PropertyChangeEvent event) {
79 if (!updating) {
80 getRealm().exec(new class() Runnable {
81 public void run() {
82 updateWrappedList(new ArrayList(Arrays
83 .asList(getValues())));
84 }
85 });
86 }
87 }
88 };
89 this.listenerSupport = new ListenerSupport(listener,
90 descriptor.getName());
91 listenerSupport.hookListener(this.object);
92 }
93
94 // initialize list without firing events
95 wrappedList.addAll(Arrays.asList(getValues()));
96 }
97
98 public void dispose() {
99 if (listenerSupport !is null) {
100 listenerSupport.dispose();
101 listenerSupport = null;
102 }
103 super.dispose();
104 }
105
106 private Object primGetValues() {
107 Exception ex = null;
108 try {
109 Method readMethod = descriptor.getReadMethod();
110 if (!readMethod.isAccessible()) {
111 readMethod.setAccessible(true);
112 }
113 return readMethod.invoke(object, new Object[0]);
114 } catch (IllegalArgumentException e) {
115 ex = e;
116 } catch (IllegalAccessException e) {
117 ex = e;
118 } catch (InvocationTargetException e) {
119 ex = e;
120 }
121 throw new BindingException("Could not read collection values", ex); //$NON-NLS-1$
122 }
123
124 private Object[] getValues() {
125 Object[] values = null;
126
127 Object result = primGetValues();
128 if (descriptor.getPropertyType().isArray())
129 values = cast(Object[]) result;
130 else {
131 // TODO add jUnit for POJO (var. SettableValue) collections
132 Collection list = cast(Collection) result;
133 if (list !is null) {
134 values = list.toArray();
135 }
136 }
137 if (values is null)
138 values = new Object[0];
139 return values;
140 }
141
142 public Object getObserved() {
143 return object;
144 }
145
146 public PropertyDescriptor getPropertyDescriptor() {
147 return descriptor;
148 }
149
150 private void setValues() {
151 if (descriptor.getPropertyType().isArray()) {
152 Class componentType = descriptor.getPropertyType()
153 .getComponentType();
154 Object[] newArray = cast(Object[]) Array.newInstance(componentType,
155 wrappedList.size());
156 wrappedList.toArray(newArray);
157 primSetValues(newArray);
158 } else {
159 // assume that it is a java.util.List
160 primSetValues(new ArrayList(wrappedList));
161 }
162 }
163
164 private void primSetValues(Object newValue) {
165 Exception ex = null;
166 try {
167 Method writeMethod = descriptor.getWriteMethod();
168 if (!writeMethod.isAccessible()) {
169 writeMethod.setAccessible(true);
170 }
171 writeMethod.invoke(object, new Object[] { newValue });
172 return;
173 } catch (IllegalArgumentException e) {
174 ex = e;
175 } catch (IllegalAccessException e) {
176 ex = e;
177 } catch (InvocationTargetException e) {
178 ex = e;
179 }
180 throw new BindingException("Could not write collection values", ex); //$NON-NLS-1$
181 }
182
183 public Object set(int index, Object element) {
184 getterCalled();
185 updating = true;
186 try {
187 Object oldElement = wrappedList.set(index, element);
188 setValues();
189 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
190 index, false, oldElement), Diffs.createListDiffEntry(index,
191 true, element)));
192 return oldElement;
193 } finally {
194 updating = false;
195 }
196 }
197
198 public Object move(int oldIndex, int newIndex) {
199 getterCalled();
200 updating = true;
201 try {
202 int size = wrappedList.size();
203 if (oldIndex < 0 || oldIndex >= size)
204 throw new IndexOutOfBoundsException(
205 "oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
206 if (newIndex < 0 || newIndex >= size)
207 throw new IndexOutOfBoundsException(
208 "newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$
209 if (oldIndex is newIndex)
210 return wrappedList.get(oldIndex);
211 Object element = wrappedList.remove(oldIndex);
212 wrappedList.add(newIndex, element);
213 setValues();
214 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
215 oldIndex, false, element), Diffs.createListDiffEntry(
216 newIndex, true, element)));
217 return element;
218 } finally {
219 updating = false;
220 }
221 }
222
223 public Object remove(int index) {
224 getterCalled();
225 updating = true;
226 try {
227 Object oldElement = wrappedList.remove(index);
228 setValues();
229 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
230 index, false, oldElement)));
231 return oldElement;
232 } finally {
233 updating = false;
234 }
235 }
236
237 public bool add(Object element) {
238 updating = true;
239 try {
240 int index = wrappedList.size();
241 bool result = wrappedList.add(element);
242 setValues();
243 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
244 index, true, element)));
245 return result;
246 } finally {
247 updating = false;
248 }
249 }
250
251 public void add(int index, Object element) {
252 updating = true;
253 try {
254 wrappedList.add(index, element);
255 setValues();
256 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
257 index, true, element)));
258 } finally {
259 updating = false;
260 }
261 }
262
263 public bool addAll(Collection c) {
264 if (c.isEmpty()) {
265 return false;
266 }
267 updating = true;
268 try {
269 int index = wrappedList.size();
270 bool result = wrappedList.addAll(c);
271 setValues();
272 ListDiffEntry[] entries = new ListDiffEntry[c.size()];
273 int i = 0;
274 for (Iterator it = c.iterator(); it.hasNext();) {
275 Object o = it.next();
276 entries[i++] = Diffs.createListDiffEntry(index++, true, o);
277 }
278 fireListChange(Diffs.createListDiff(entries));
279 return result;
280 } finally {
281 updating = false;
282 }
283 }
284
285 public bool addAll(int index, Collection c) {
286 if (c.isEmpty()) {
287 return false;
288 }
289 updating = true;
290 try {
291 bool result = wrappedList.addAll(index, c);
292 setValues();
293 ListDiffEntry[] entries = new ListDiffEntry[c.size()];
294 int i = 0;
295 for (Iterator it = c.iterator(); it.hasNext();) {
296 Object o = it.next();
297 entries[i++] = Diffs.createListDiffEntry(index++, true, o);
298 }
299 fireListChange(Diffs.createListDiff(entries));
300 return result;
301 } finally {
302 updating = false;
303 }
304 }
305
306 public bool remove(Object o) {
307 getterCalled();
308 int index = wrappedList.indexOf(o);
309 if (index is -1) {
310 return false;
311 }
312 updating = true;
313 try {
314 Object oldElement = wrappedList.remove(index);
315 setValues();
316 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
317 index, false, oldElement)));
318 return true;
319 } finally {
320 updating = false;
321 }
322 }
323
324 public bool removeAll(Collection c) {
325 getterCalled();
326 bool changed = false;
327 updating = true;
328 try {
329 List diffEntries = new ArrayList();
330 for (Iterator it = c.iterator(); it.hasNext();) {
331 Object o = it.next();
332 int index = wrappedList.indexOf(o);
333 if (index !is -1) {
334 changed = true;
335 Object oldElement = wrappedList.remove(index);
336 diffEntries.add(Diffs.createListDiffEntry(index, false,
337 oldElement));
338 }
339 }
340 if (changed) {
341 setValues();
342 fireListChange(Diffs
343 .createListDiff(cast(ListDiffEntry[]) diffEntries
344 .toArray(new ListDiffEntry[diffEntries.size()])));
345 }
346 return changed;
347 } finally {
348 updating = false;
349 }
350 }
351
352 public bool retainAll(Collection c) {
353 getterCalled();
354 bool changed = false;
355 updating = true;
356 try {
357 List diffEntries = new ArrayList();
358 int index = 0;
359 for (Iterator it = wrappedList.iterator(); it.hasNext();) {
360 Object o = it.next();
361 bool retain = c.contains(o);
362 if (retain) {
363 index++;
364 } else {
365 changed = true;
366 it.remove();
367 diffEntries.add(Diffs.createListDiffEntry(index, false, o));
368 }
369 }
370 if (changed) {
371 setValues();
372 fireListChange(Diffs
373 .createListDiff(cast(ListDiffEntry[]) diffEntries
374 .toArray(new ListDiffEntry[diffEntries.size()])));
375 }
376 return changed;
377 } finally {
378 updating = false;
379 }
380 }
381
382 public void clear() {
383 updating = true;
384 try {
385 List diffEntries = new ArrayList();
386 for (Iterator it = wrappedList.iterator(); it.hasNext();) {
387 Object o = it.next();
388 diffEntries.add(Diffs.createListDiffEntry(0, false, o));
389 }
390 wrappedList.clear();
391 setValues();
392 fireListChange(Diffs.createListDiff(cast(ListDiffEntry[]) diffEntries
393 .toArray(new ListDiffEntry[diffEntries.size()])));
394 } finally {
395 updating = false;
396 }
397 }
398
399 }