1 12 13 package org.eclipse.core.internal.databinding.internal.beans; 14 15 import java.beans.PropertyChangeListener ; 16 import java.beans.PropertyDescriptor ; 17 import java.lang.reflect.Array ; 18 import java.lang.reflect.InvocationTargetException ; 19 import java.lang.reflect.Method ; 20 import java.util.ArrayList ; 21 import java.util.Arrays ; 22 import java.util.Collection ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 26 import org.eclipse.core.databinding.BindingException; 27 import org.eclipse.core.databinding.beans.IBeanObservable; 28 import org.eclipse.core.databinding.observable.Diffs; 29 import org.eclipse.core.databinding.observable.Realm; 30 import org.eclipse.core.databinding.observable.list.ListDiffEntry; 31 import org.eclipse.core.databinding.observable.list.ObservableList; 32 33 37 public class JavaBeanObservableList extends ObservableList implements 38 IBeanObservable { 39 40 private final Object object; 41 42 private PropertyChangeListener collectionListener = new PropertyChangeListener () { 43 public void propertyChange(java.beans.PropertyChangeEvent event) { 44 if (!updating) { 45 updateWrappedList(Arrays.asList(getValues())); 46 } 47 } 48 }; 49 50 private boolean updating = false; 51 52 private PropertyDescriptor descriptor; 53 54 private ListenerSupport collectionListenSupport; 55 56 62 public JavaBeanObservableList(Realm realm, Object object, 63 PropertyDescriptor descriptor, Class elementType) { 64 super(realm, new ArrayList (), elementType); 65 this.object = object; 66 this.descriptor = descriptor; 67 this.collectionListenSupport = new ListenerSupport(collectionListener, 68 descriptor.getName()); 69 70 wrappedList.addAll(Arrays.asList(getValues())); 72 } 73 74 protected void firstListenerAdded() { 75 collectionListenSupport.hookListener(this.object); 76 } 77 78 protected void lastListenerRemoved() { 79 if (collectionListenSupport != null) { 80 collectionListenSupport.dispose(); 81 } 82 } 83 84 public void dispose() { 85 super.dispose(); 86 lastListenerRemoved(); 87 } 88 89 private Object primGetValues() { 90 Exception ex = null; 91 try { 92 Method readMethod = descriptor.getReadMethod(); 93 if (!readMethod.isAccessible()) { 94 readMethod.setAccessible(true); 95 } 96 return readMethod.invoke(object, new Object [0]); 97 } catch (IllegalArgumentException e) { 98 ex = e; 99 } catch (IllegalAccessException e) { 100 ex = e; 101 } catch (InvocationTargetException e) { 102 ex = e; 103 } 104 throw new BindingException("Could not read collection values", ex); } 106 107 private Object [] getValues() { 108 Object [] values = null; 109 110 Object result = primGetValues(); 111 if (descriptor.getPropertyType().isArray()) 112 values = (Object []) result; 113 else { 114 Collection list = (Collection ) result; 116 if (list != null) { 117 values = list.toArray(); 118 } else { 119 values = new Object [] {}; 120 } 121 } 122 return values; 123 } 124 125 public Object getObserved() { 126 return object; 127 } 128 129 public PropertyDescriptor getPropertyDescriptor() { 130 return descriptor; 131 } 132 133 private void setValues() { 134 if (descriptor.getPropertyType().isArray()) { 135 Class componentType = descriptor.getPropertyType() 136 .getComponentType(); 137 Object [] newArray = (Object []) Array.newInstance(componentType, 138 wrappedList.size()); 139 wrappedList.toArray(newArray); 140 primSetValues(newArray); 141 } else { 142 primSetValues(new ArrayList (wrappedList)); 144 } 145 } 146 147 private void primSetValues(Object newValue) { 148 Exception ex = null; 149 try { 150 Method writeMethod = descriptor.getWriteMethod(); 151 if (!writeMethod.isAccessible()) { 152 writeMethod.setAccessible(true); 153 } 154 writeMethod.invoke(object, new Object [] { newValue }); 155 return; 156 } catch (IllegalArgumentException e) { 157 ex = e; 158 } catch (IllegalAccessException e) { 159 ex = e; 160 } catch (InvocationTargetException e) { 161 ex = e; 162 } 163 throw new BindingException("Could not write collection values", ex); } 165 166 public Object set(int index, Object element) { 167 getterCalled(); 168 updating = true; 169 try { 170 Object oldElement = wrappedList.set(index, element); 171 setValues(); 172 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( 173 index, true, element), Diffs.createListDiffEntry(index + 1, 174 false, oldElement))); 175 return oldElement; 176 } finally { 177 updating = false; 178 } 179 } 180 181 public Object remove(int index) { 182 getterCalled(); 183 updating = true; 184 try { 185 Object oldElement = wrappedList.remove(index); 186 setValues(); 187 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( 188 index, false, oldElement))); 189 return oldElement; 190 } finally { 191 updating = false; 192 } 193 } 194 195 public boolean add(Object element) { 196 updating = true; 197 try { 198 int index = wrappedList.size(); 199 boolean result = wrappedList.add(element); 200 setValues(); 201 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( 202 index, true, element))); 203 return result; 204 } finally { 205 updating = false; 206 } 207 } 208 209 public void add(int index, Object element) { 210 updating = true; 211 try { 212 wrappedList.add(index, element); 213 setValues(); 214 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( 215 index, true, element))); 216 } finally { 217 updating = false; 218 } 219 } 220 221 public boolean addAll(Collection c) { 222 if (c.isEmpty()) { 223 return false; 224 } 225 updating = true; 226 try { 227 int index = wrappedList.size(); 228 boolean result = wrappedList.addAll(c); 229 setValues(); 230 ListDiffEntry[] entries = new ListDiffEntry[c.size()]; 231 int i = 0; 232 for (Iterator it = c.iterator(); it.hasNext();) { 233 Object o = it.next(); 234 entries[i++] = Diffs.createListDiffEntry(index++, true, o); 235 } 236 fireListChange(Diffs.createListDiff(entries)); 237 return result; 238 } finally { 239 updating = false; 240 } 241 } 242 243 public boolean addAll(int index, Collection c) { 244 if (c.isEmpty()) { 245 return false; 246 } 247 updating = true; 248 try { 249 boolean result = wrappedList.addAll(index, c); 250 setValues(); 251 ListDiffEntry[] entries = new ListDiffEntry[c.size()]; 252 int i = 0; 253 for (Iterator it = c.iterator(); it.hasNext();) { 254 Object o = it.next(); 255 entries[i++] = Diffs.createListDiffEntry(index++, true, o); 256 } 257 fireListChange(Diffs.createListDiff(entries)); 258 return result; 259 } finally { 260 updating = false; 261 } 262 } 263 264 public boolean remove(Object o) { 265 getterCalled(); 266 int index = wrappedList.indexOf(o); 267 if (index == -1) { 268 return false; 269 } 270 updating = true; 271 try { 272 Object oldElement = wrappedList.remove(index); 273 setValues(); 274 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( 275 index, false, oldElement))); 276 return true; 277 } finally { 278 updating = false; 279 } 280 } 281 282 public boolean removeAll(Collection c) { 283 getterCalled(); 284 boolean changed = false; 285 updating = true; 286 try { 287 List diffEntries = new ArrayList (); 288 for (Iterator it = c.iterator(); it.hasNext();) { 289 Object o = it.next(); 290 int index = wrappedList.indexOf(o); 291 if (index != -1) { 292 changed = true; 293 Object oldElement = wrappedList.remove(index); 294 diffEntries.add(Diffs.createListDiffEntry(index, false, 295 oldElement)); 296 } 297 } 298 setValues(); 299 fireListChange(Diffs.createListDiff((ListDiffEntry[]) diffEntries 300 .toArray(new ListDiffEntry[diffEntries.size()]))); 301 return changed; 302 } finally { 303 updating = false; 304 } 305 } 306 307 public boolean retainAll(Collection c) { 308 getterCalled(); 309 boolean changed = false; 310 updating = true; 311 try { 312 List diffEntries = new ArrayList (); 313 int index = 0; 314 for (Iterator it = wrappedList.iterator(); it.hasNext();) { 315 Object o = it.next(); 316 boolean retain = c.contains(o); 317 if (retain) { 318 index++; 319 } else { 320 changed = true; 321 it.remove(); 322 diffEntries.add(Diffs.createListDiffEntry(index, false, o)); 323 } 324 } 325 setValues(); 326 fireListChange(Diffs.createListDiff((ListDiffEntry[]) diffEntries 327 .toArray(new ListDiffEntry[diffEntries.size()]))); 328 return changed; 329 } finally { 330 updating = false; 331 } 332 } 333 334 public void clear() { 335 updating = true; 336 try { 337 List diffEntries = new ArrayList (); 338 for (Iterator it = wrappedList.iterator(); it.hasNext();) { 339 Object o = it.next(); 340 diffEntries.add(Diffs.createListDiffEntry(0, false, o)); 341 } 342 setValues(); 343 fireListChange(Diffs.createListDiff((ListDiffEntry[]) diffEntries 344 .toArray(new ListDiffEntry[diffEntries.size()]))); 345 } finally { 346 updating = false; 347 } 348 } 349 350 } 351 | Popular Tags |