Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 117279 Details for
Bug 246103
[DataBinding] JavaBeanObservableValue does not generate correct ValueDiff when oldValue == newValue == null
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
patch
clipboard.txt (text/plain), 44.36 KB, created by
Matthew Hall
on 2008-11-06 21:01:43 EST
(
hide
)
Description:
patch
Filename:
MIME Type:
Creator:
Matthew Hall
Created:
2008-11-06 21:01:43 EST
Size:
44.36 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.core.databinding >Index: src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java,v >retrieving revision 1.10 >diff -u -r1.10 AbstractObservableMap.java >--- src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java 17 Oct 2008 16:44:25 -0000 1.10 >+++ src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java 7 Nov 2008 01:59:38 -0000 >@@ -8,7 +8,7 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Brad Reynolds - bug 164653 >- * Matthew Hall - bugs 118516, 146397, 226289 >+ * Matthew Hall - bugs 118516, 146397, 226289, 246103 > *******************************************************************************/ > > package org.eclipse.core.databinding.observable.map; >@@ -38,7 +38,25 @@ > public abstract class AbstractObservableMap extends AbstractMap implements > IObservableMap { > >- private ChangeSupport changeSupport; >+ private final class PrivateChangeSupport extends ChangeSupport { >+ private PrivateChangeSupport(Realm realm) { >+ super(realm); >+ } >+ >+ protected void firstListenerAdded() { >+ AbstractObservableMap.this.firstListenerAdded(); >+ } >+ >+ protected void lastListenerRemoved() { >+ AbstractObservableMap.this.lastListenerRemoved(); >+ } >+ >+ protected boolean hasListeners() { >+ return super.hasListeners(); >+ } >+ } >+ >+ private PrivateChangeSupport changeSupport; > private boolean disposed = false; > > private boolean stale; >@@ -66,14 +84,7 @@ > */ > public AbstractObservableMap(Realm realm) { > Assert.isNotNull(realm, "Realm cannot be null"); //$NON-NLS-1$ >- changeSupport = new ChangeSupport(realm){ >- protected void firstListenerAdded() { >- AbstractObservableMap.this.firstListenerAdded(); >- } >- protected void lastListenerRemoved() { >- AbstractObservableMap.this.lastListenerRemoved(); >- } >- }; >+ changeSupport = new PrivateChangeSupport(realm); > } > > public synchronized void addMapChangeListener(IMapChangeListener listener) { >@@ -97,6 +108,14 @@ > } > > /** >+ * @return whether the observable map has listeners registered >+ * @since 1.2 >+ */ >+ protected synchronized boolean hasListeners() { >+ return !disposed && changeSupport.hasListeners(); >+ } >+ >+ /** > * @since 1.2 > */ > public void addDisposeListener(IDisposeListener listener) { >#P org.eclipse.jface.tests.databinding >Index: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableMapTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableMapTest.java,v >retrieving revision 1.4 >diff -u -r1.4 JavaBeanObservableMapTest.java >--- src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableMapTest.java 21 Jul 2008 20:59:39 -0000 1.4 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableMapTest.java 7 Nov 2008 01:59:40 -0000 >@@ -7,20 +7,23 @@ > * > * Contributors: > * IBM Corporation - initial API and implementation >- * Matthew Hall - bugs 213145, 241585 >+ * Matthew Hall - bugs 213145, 241585, 246103 > *******************************************************************************/ > > package org.eclipse.core.tests.internal.databinding.beans; > > import java.beans.PropertyDescriptor; >+import java.util.Collections; > import java.util.HashSet; > > import junit.framework.Test; > import junit.framework.TestCase; > import junit.framework.TestSuite; > >+import org.eclipse.core.databinding.beans.BeansObservables; > import org.eclipse.core.databinding.observable.Realm; > import org.eclipse.core.databinding.observable.map.IMapChangeListener; >+import org.eclipse.core.databinding.observable.map.IObservableMap; > import org.eclipse.core.databinding.observable.map.MapChangeEvent; > import org.eclipse.core.databinding.observable.map.MapDiff; > import org.eclipse.core.databinding.observable.set.WritableSet; >@@ -28,6 +31,7 @@ > import org.eclipse.core.tests.databinding.observable.ThreadRealm; > import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker; > import org.eclipse.jface.databinding.conformance.util.CurrentRealm; >+import org.eclipse.jface.databinding.conformance.util.MapChangeEventTracker; > > /** > * @since 3.2 >@@ -166,6 +170,37 @@ > assertTrue(bean.hasListeners("value")); > } > >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a >+ // PropertyChangeEvent to be null, which indicates that an unknown >+ // change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct >+ // value diff even if the bean implementor is lazy :-P >+ >+ WritableSet set = new WritableSet(new CurrentRealm(true)); >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setValue("old"); >+ set.add(bean); >+ >+ IObservableMap map = BeansObservables.observeMap(set, Bean.class, >+ "value"); >+ MapChangeEventTracker tracker = MapChangeEventTracker.observe(map); >+ >+ bean.setValue("new"); >+ >+ assertEquals(1, tracker.count); >+ >+ assertEquals(Collections.EMPTY_SET, tracker.event.diff.getAddedKeys()); >+ assertEquals(Collections.singleton(bean), tracker.event.diff >+ .getChangedKeys()); >+ assertEquals(Collections.EMPTY_SET, tracker.event.diff.getRemovedKeys()); >+ >+ assertEquals("old", tracker.event.diff.getOldValue(bean)); >+ assertEquals("new", tracker.event.diff.getNewValue(bean)); >+ } >+ > private static class MapChangeListener implements IMapChangeListener { > int count; > >Index: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableValueTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableValueTest.java,v >retrieving revision 1.2 >diff -u -r1.2 JavaBeanObservableValueTest.java >--- src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableValueTest.java 20 Mar 2008 21:16:40 -0000 1.2 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableValueTest.java 7 Nov 2008 01:59:40 -0000 >@@ -9,7 +9,7 @@ > * Brad Reynolds - initial API and implementation > * Brad Reynolds - bug 171616 > * Katarzyna Marszalek - test case for bug 198519 >- * Matthew Hall - bug 213145 >+ * Matthew Hall - bug 213145, 246103 > ******************************************************************************/ > > package org.eclipse.core.tests.internal.databinding.beans; >@@ -31,6 +31,7 @@ > import org.eclipse.jface.databinding.conformance.MutableObservableValueContractTest; > import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableValueContractDelegate; > import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker; >+import org.eclipse.jface.databinding.conformance.util.ValueChangeEventTracker; > import org.eclipse.jface.examples.databinding.model.SimplePerson; > import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; > >@@ -121,6 +122,23 @@ > assertFalse(bean.hasListeners(propertyName)); > } > >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a PropertyChangeEvent to >+ // be null, which indicates that an unknown change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct value diff >+ // even if the bean implementor is lazy :-P >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setValue("old"); >+ IObservableValue observable = BeansObservables.observeValue(bean, "value"); >+ ValueChangeEventTracker tracker = ValueChangeEventTracker.observe(observable); >+ bean.setValue("new"); >+ assertEquals(1, tracker.count); >+ assertEquals("old", tracker.event.diff.getOldValue()); >+ assertEquals("new", tracker.event.diff.getNewValue()); >+ } >+ > public static Test suite() { > TestSuite suite = new TestSuite(JavaBeanObservableValueTest.class.getName()); > suite.addTestSuite(JavaBeanObservableValueTest.class); >Index: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedListTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedListTest.java,v >retrieving revision 1.3 >diff -u -r1.3 JavaBeanObservableArrayBasedListTest.java >--- src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedListTest.java 26 Oct 2008 13:06:53 -0000 1.3 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedListTest.java 7 Nov 2008 01:59:39 -0000 >@@ -7,7 +7,7 @@ > * > * Contributors: > * Brad Reynolds - initial API and implementation >- * Matthew Hall - bugs 221351, 213145, 244098 >+ * Matthew Hall - bugs 221351, 213145, 244098, 246103 > ******************************************************************************/ > > package org.eclipse.core.tests.internal.databinding.beans; >@@ -16,13 +16,16 @@ > import java.beans.PropertyChangeEvent; > import java.beans.PropertyChangeListener; > import java.beans.PropertyDescriptor; >+import java.util.ArrayList; > import java.util.Arrays; > import java.util.Collection; >+import java.util.Collections; > import java.util.List; > > import junit.framework.Test; > import junit.framework.TestSuite; > >+import org.eclipse.core.databinding.beans.BeansObservables; > import org.eclipse.core.databinding.observable.IObservable; > import org.eclipse.core.databinding.observable.IObservableCollection; > import org.eclipse.core.databinding.observable.Realm; >@@ -32,6 +35,7 @@ > import org.eclipse.core.internal.databinding.beans.JavaBeanObservableList; > import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest; > import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate; >+import org.eclipse.jface.databinding.conformance.util.CurrentRealm; > import org.eclipse.jface.databinding.conformance.util.ListChangeEventTracker; > import org.eclipse.jface.databinding.swt.SWTObservables; > import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; >@@ -446,6 +450,29 @@ > assertEquals(1, listener.count); > } > >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a >+ // PropertyChangeEvent to be null, which indicates that an unknown >+ // change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct >+ // value diff even if the bean implementor is lazy :-P >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setArray(new Object[] { "old" }); >+ IObservableList observable = BeansObservables.observeList( >+ new CurrentRealm(true), bean, "array"); >+ ListChangeEventTracker tracker = ListChangeEventTracker >+ .observe(observable); >+ bean.setArray(new Object[] { "new" }); >+ assertEquals(1, tracker.count); >+ >+ List list = new ArrayList(); >+ list.add("old"); >+ tracker.event.diff.applyTo(list); >+ assertEquals(Collections.singletonList("new"), list); >+ } >+ > private static void assertEntry(ListDiffEntry entry, boolean addition, > int position, Object element) { > assertEquals("addition", addition, entry.isAddition()); >Index: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableSetTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableSetTest.java,v >retrieving revision 1.3 >diff -u -r1.3 JavaBeanObservableSetTest.java >--- src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableSetTest.java 26 Oct 2008 13:06:53 -0000 1.3 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableSetTest.java 7 Nov 2008 01:59:40 -0000 >@@ -7,7 +7,7 @@ > * > * Contributors: > * Brad Reynolds - initial API and implementation >- * Matthew Hall - bugs 221351, 213145, 244098 >+ * Matthew Hall - bugs 221351, 213145, 244098, 246103 > ******************************************************************************/ > > package org.eclipse.core.tests.internal.databinding.beans; >@@ -15,12 +15,14 @@ > import java.beans.IntrospectionException; > import java.beans.PropertyDescriptor; > import java.util.Arrays; >+import java.util.Collections; > import java.util.HashSet; > > import junit.framework.Test; > import junit.framework.TestCase; > import junit.framework.TestSuite; > >+import org.eclipse.core.databinding.beans.BeansObservables; > import org.eclipse.core.databinding.observable.IObservable; > import org.eclipse.core.databinding.observable.IObservableCollection; > import org.eclipse.core.databinding.observable.Realm; >@@ -32,6 +34,7 @@ > import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate; > import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker; > import org.eclipse.jface.databinding.conformance.util.CurrentRealm; >+import org.eclipse.jface.databinding.conformance.util.SetChangeEventTracker; > import org.eclipse.jface.databinding.swt.SWTObservables; > import org.eclipse.swt.widgets.Display; > >@@ -105,7 +108,29 @@ > ChangeEventTracker.observe(observableSet); > assertFalse(bean.hasListeners(propertyName)); > } >- >+ >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a >+ // PropertyChangeEvent to be null, which indicates that an unknown >+ // change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct >+ // value diff even if the bean implementor is lazy :-P >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setSet(Collections.singleton("old")); >+ IObservableSet observable = BeansObservables.observeSet( >+ new CurrentRealm(true), bean, "set"); >+ SetChangeEventTracker tracker = SetChangeEventTracker >+ .observe(observable); >+ bean.setSet(Collections.singleton("new")); >+ assertEquals(1, tracker.count); >+ assertEquals(Collections.singleton("old"), tracker.event.diff >+ .getRemovals()); >+ assertEquals(Collections.singleton("new"), tracker.event.diff >+ .getAdditions()); >+ } >+ > static class SetChangeListener implements ISetChangeListener { > int count; > public void handleSetChange(SetChangeEvent event) { >Index: src/org/eclipse/core/tests/internal/databinding/beans/Bean.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/Bean.java,v >retrieving revision 1.1 >diff -u -r1.1 Bean.java >--- src/org/eclipse/core/tests/internal/databinding/beans/Bean.java 19 Mar 2008 23:03:19 -0000 1.1 >+++ src/org/eclipse/core/tests/internal/databinding/beans/Bean.java 7 Nov 2008 01:59:39 -0000 >@@ -15,6 +15,7 @@ > import java.beans.PropertyChangeListener; > import java.beans.PropertyChangeSupport; > import java.util.List; >+import java.util.Map; > import java.util.Set; > > /** >@@ -23,12 +24,13 @@ > * @since 3.3 > */ > public class Bean { >- /* package */PropertyChangeSupport changeSupport = new PropertyChangeSupport( >+ protected PropertyChangeSupport changeSupport = new PropertyChangeSupport( > this); >- private String value; >- private Object[] array; >- private List list; >- private Set set; >+ protected String value; >+ protected Object[] array; >+ protected List list; >+ protected Set set; >+ protected Map map; > > public Bean() { > } >@@ -49,6 +51,10 @@ > this.set = set; > } > >+ public Bean(Map map) { >+ this.map = map; >+ } >+ > public void addPropertyChangeListener(PropertyChangeListener listener) { > changeSupport.addPropertyChangeListener(listener); > } >@@ -91,6 +97,14 @@ > changeSupport.firePropertyChange("set", this.set, this.set = set); > } > >+ public Map getMap() { >+ return map; >+ } >+ >+ public void setMap(Map map) { >+ changeSupport.firePropertyChange("map", this.map, this.map = map); >+ } >+ > public boolean hasListeners(String propertyName) { > return changeSupport.hasListeners(propertyName); > } >Index: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedSetTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedSetTest.java,v >retrieving revision 1.3 >diff -u -r1.3 JavaBeanObservableArrayBasedSetTest.java >--- src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedSetTest.java 26 Oct 2008 13:06:53 -0000 1.3 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableArrayBasedSetTest.java 7 Nov 2008 01:59:39 -0000 >@@ -8,7 +8,7 @@ > * Contributors: > * Matthew Hall - initial API and implementation (bug 221351) > * Brad Reynolds - through JavaBeanObservableArrayBasedListTest.java >- * Matthew Hall - bug 213145, 244098 >+ * Matthew Hall - bug 213145, 244098, 246103 > ******************************************************************************/ > > package org.eclipse.core.tests.internal.databinding.beans; >@@ -25,6 +25,7 @@ > import junit.framework.Test; > import junit.framework.TestSuite; > >+import org.eclipse.core.databinding.beans.BeansObservables; > import org.eclipse.core.databinding.observable.IObservable; > import org.eclipse.core.databinding.observable.IObservableCollection; > import org.eclipse.core.databinding.observable.Realm; >@@ -33,6 +34,7 @@ > import org.eclipse.core.internal.databinding.beans.JavaBeanObservableSet; > import org.eclipse.jface.databinding.conformance.MutableObservableSetContractTest; > import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate; >+import org.eclipse.jface.databinding.conformance.util.CurrentRealm; > import org.eclipse.jface.databinding.conformance.util.SetChangeEventTracker; > import org.eclipse.jface.databinding.swt.SWTObservables; > import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; >@@ -129,7 +131,7 @@ > assertEquals(0, bean.getArray().length); > } > >- public void testRemoveListChangeEvent() throws Exception { >+ public void testRemove_SetChangeEvent() throws Exception { > String element = "1"; > set.add(element); > assertEquals(1, set.size()); >@@ -165,7 +167,7 @@ > assertEquals(2, bean.getArray().length); > } > >- public void testAddAllListChangEvent() throws Exception { >+ public void testAddAll_SetChangeEvent() throws Exception { > Collection elements = Arrays.asList(new String[] { "1", "2" }); > assertEquals(0, set.size()); > >@@ -200,7 +202,7 @@ > assertEquals(0, bean.getArray().length); > } > >- public void testRemoveAllListChangeEvent() throws Exception { >+ public void testRemoveAll_SetChangeEvent() throws Exception { > Collection elements = Arrays.asList(new String[] { "1", "2" }); > set.addAll(elements); > >@@ -235,7 +237,7 @@ > assertTrue(set.containsAll(Arrays.asList(new String[] { "1", "0" }))); > } > >- public void testRetainAllListChangeEvent() throws Exception { >+ public void testRetainAll_SetChangeEvent() throws Exception { > set.addAll(Arrays.asList(new String[] { "0", "1", "2", "3" })); > > SetChangeEventTracker listener = SetChangeEventTracker.observe(set); >@@ -261,7 +263,7 @@ > }); > } > >- public void testListChangeEventFiresWhenNewListIsSet() throws Exception { >+ public void testSetChangeEventFiresWhenNewSetIsSet() throws Exception { > Bean[] elements = new Bean[] { new Bean(), new Bean() }; > > SetChangeEventTracker listener = SetChangeEventTracker.observe(set); >@@ -271,6 +273,28 @@ > assertEquals(1, listener.count); > } > >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a >+ // PropertyChangeEvent to be null, which indicates that an unknown >+ // change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct >+ // value diff even if the bean implementor is lazy :-P >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setArray(new Object[] { "old" }); >+ IObservableSet observable = BeansObservables.observeSet( >+ new CurrentRealm(true), bean, "array"); >+ SetChangeEventTracker tracker = SetChangeEventTracker >+ .observe(observable); >+ bean.setArray(new Object[] { "new" }); >+ assertEquals(1, tracker.count); >+ assertEquals(Collections.singleton("old"), tracker.event.diff >+ .getRemovals()); >+ assertEquals(Collections.singleton("new"), tracker.event.diff >+ .getAdditions()); >+ } >+ > private static void assertPropertyChangeEvent(Bean bean, Runnable runnable) { > PropertyChangeTracker listener = new PropertyChangeTracker(); > bean.addPropertyChangeListener(listener); >@@ -286,7 +310,7 @@ > assertTrue("old value", Arrays.equals(old, (Object[]) event > .getOldValue())); > assertTrue("new value", Arrays.equals(bean.getArray(), (Object[]) event.getNewValue())); >- assertFalse("lists are equal", Arrays.equals(bean.getArray(), old)); >+ assertFalse("sets are equal", Arrays.equals(bean.getArray(), old)); > } > > private static class PropertyChangeTracker implements >@@ -326,11 +350,11 @@ > } > Object bean = new Bean(new Object[0]); > >- IObservableSet list = new JavaBeanObservableSet(realm, bean, >+ IObservableSet set = new JavaBeanObservableSet(realm, bean, > propertyDescriptor, String.class); > for (int i = 0; i < elementCount; i++) >- list.add(createElement(list)); >- return list; >+ set.add(createElement(set)); >+ return set; > } > > public Object createElement(IObservableCollection collection) { >@@ -342,8 +366,8 @@ > } > > public void change(IObservable observable) { >- IObservableSet list = (IObservableSet) observable; >- list.add(createElement(list)); >+ IObservableSet set = (IObservableSet) observable; >+ set.add(createElement(set)); > } > } > } >Index: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableListTest.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableListTest.java,v >retrieving revision 1.4 >diff -u -r1.4 JavaBeanObservableListTest.java >--- src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableListTest.java 26 Oct 2008 13:06:53 -0000 1.4 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanObservableListTest.java 7 Nov 2008 01:59:40 -0000 >@@ -7,7 +7,7 @@ > * > * Contributors: > * Brad Reynolds - initial API and implementation >- * Matthew Hall - bugs 221351, 213145, 244098 >+ * Matthew Hall - bugs 221351, 213145, 244098, 246103 > ******************************************************************************/ > > package org.eclipse.core.tests.internal.databinding.beans; >@@ -19,11 +19,13 @@ > import java.util.ArrayList; > import java.util.Arrays; > import java.util.Collection; >+import java.util.Collections; > import java.util.List; > > import junit.framework.Test; > import junit.framework.TestSuite; > >+import org.eclipse.core.databinding.beans.BeansObservables; > import org.eclipse.core.databinding.observable.IObservable; > import org.eclipse.core.databinding.observable.IObservableCollection; > import org.eclipse.core.databinding.observable.Realm; >@@ -34,6 +36,7 @@ > import org.eclipse.jface.databinding.conformance.MutableObservableListContractTest; > import org.eclipse.jface.databinding.conformance.delegate.AbstractObservableCollectionContractDelegate; > import org.eclipse.jface.databinding.conformance.util.ChangeEventTracker; >+import org.eclipse.jface.databinding.conformance.util.CurrentRealm; > import org.eclipse.jface.databinding.conformance.util.ListChangeEventTracker; > import org.eclipse.jface.databinding.swt.SWTObservables; > import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; >@@ -476,6 +479,30 @@ > assertFalse(bean.hasListeners("list")); > } > >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a >+ // PropertyChangeEvent to be null, which indicates that an unknown >+ // change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct >+ // value diff even if the bean implementor is lazy :-P >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setList(Collections.singletonList("old")); >+ IObservableList observable = BeansObservables.observeList( >+ new CurrentRealm(true), bean, "list"); >+ ListChangeEventTracker tracker = ListChangeEventTracker >+ .observe(observable); >+ bean.setList(Collections.singletonList("new")); >+ >+ assertEquals(1, tracker.count); >+ >+ List list = new ArrayList(); >+ list.add("old"); >+ tracker.event.diff.applyTo(list); >+ assertEquals(Collections.singletonList("new"), list); >+ } >+ > private static void assertEntry(ListDiffEntry entry, boolean addition, > int position, Object element) { > assertEquals("addition", addition, entry.isAddition()); >Index: src/org/eclipse/jface/tests/databinding/BindingTestSuite.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.tests.databinding/src/org/eclipse/jface/tests/databinding/BindingTestSuite.java,v >retrieving revision 1.94 >diff -u -r1.94 BindingTestSuite.java >--- src/org/eclipse/jface/tests/databinding/BindingTestSuite.java 29 Sep 2008 16:55:38 -0000 1.94 >+++ src/org/eclipse/jface/tests/databinding/BindingTestSuite.java 7 Nov 2008 01:59:40 -0000 >@@ -13,7 +13,7 @@ > * Ashley Cambrell - bugs 198903, 198904 > * Matthew Hall - bugs 210115, 212468, 212223, 206839, 208858, 208322, > * 212518, 215531, 221351, 184830, 213145, 218269, 239015, >- * 237703, 237718, 222289, 247394, 233306, 247647 >+ * 237703, 237718, 222289, 247394, 233306, 247647, 246103 > * Ovidio Mallo - bug 237163, bug 235195 > *******************************************************************************/ > package org.eclipse.jface.tests.databinding; >@@ -80,6 +80,7 @@ > import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableMapTest; > import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableSetTest; > import org.eclipse.core.tests.internal.databinding.beans.JavaBeanObservableValueTest; >+import org.eclipse.core.tests.internal.databinding.beans.JavaBeanPropertyObservableMapTest; > import org.eclipse.core.tests.internal.databinding.beans.ListenerSupportTest; > import org.eclipse.core.tests.internal.databinding.conversion.DateConversionSupportTest; > import org.eclipse.core.tests.internal.databinding.conversion.IdentityConverterTest; >@@ -303,6 +304,7 @@ > addTest(JavaBeanObservableMapTest.suite()); > addTest(JavaBeanObservableSetTest.suite()); > addTest(JavaBeanObservableValueTest.suite()); >+ addTestSuite(JavaBeanPropertyObservableMapTest.class); > addTestSuite(ListenerSupportTest.class); > > //org.eclipse.core.tests.internal.databinding.observable >Index: src/org/eclipse/core/tests/internal/databinding/beans/AnnoyingBean.java >=================================================================== >RCS file: src/org/eclipse/core/tests/internal/databinding/beans/AnnoyingBean.java >diff -N src/org/eclipse/core/tests/internal/databinding/beans/AnnoyingBean.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/tests/internal/databinding/beans/AnnoyingBean.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,50 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 246103) >+ ******************************************************************************/ >+ >+package org.eclipse.core.tests.internal.databinding.beans; >+ >+import java.util.List; >+import java.util.Map; >+import java.util.Set; >+ >+/** >+ * A bean in which all property change events are fired according to an annoying >+ * provision in the bean spec, where <code>(oldValue == null && newValue == >+ * null)</code> indicates that an unknown change occured. >+ * >+ * @since 3.2 >+ */ >+public class AnnoyingBean extends Bean { >+ public void setValue(String value) { >+ this.value = value; >+ changeSupport.firePropertyChange("value", null, null); >+ } >+ >+ public void setArray(Object[] array) { >+ this.array = array; >+ changeSupport.firePropertyChange("array", null, null); >+ } >+ >+ public void setList(List list) { >+ this.list = list; >+ changeSupport.firePropertyChange("list", null, null); >+ } >+ >+ public void setSet(Set set) { >+ this.set = set; >+ changeSupport.firePropertyChange("set", null, null); >+ } >+ >+ public void setMap(Map map) { >+ this.map = map; >+ changeSupport.firePropertyChange("map", null, null); >+ } >+} >\ No newline at end of fileIndex: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanPropertyObservableMapTest.java >=================================================================== >RCS file: src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanPropertyObservableMapTest.java >diff -N src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanPropertyObservableMapTest.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/tests/internal/databinding/beans/JavaBeanPropertyObservableMapTest.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,56 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * Matthew Hall - initial API and implementation (bug 246103) >+ ******************************************************************************/ >+ >+package org.eclipse.core.tests.internal.databinding.beans; >+ >+import java.util.Collections; >+ >+import org.eclipse.core.databinding.beans.BeansObservables; >+import org.eclipse.core.databinding.observable.map.IObservableMap; >+import org.eclipse.jface.databinding.conformance.util.CurrentRealm; >+import org.eclipse.jface.databinding.conformance.util.MapChangeEventTracker; >+import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; >+ >+/** >+ * @since 3.2 >+ * >+ */ >+public class JavaBeanPropertyObservableMapTest extends >+ AbstractDefaultRealmTestCase { >+ public void testSetBeanProperty_CorrectForNullOldAndNewValues() { >+ // The java bean spec allows the old and new values in a >+ // PropertyChangeEvent to be null, which indicates that an unknown >+ // change occured. >+ >+ // This test ensures that JavaBeanObservableValue fires the correct >+ // value diff even if the bean implementor is lazy :-P >+ >+ Bean bean = new AnnoyingBean(); >+ bean.setMap(Collections.singletonMap("key", "old")); >+ >+ IObservableMap map = BeansObservables.observeMap( >+ new CurrentRealm(true), bean, "map"); >+ MapChangeEventTracker tracker = MapChangeEventTracker.observe(map); >+ >+ bean.setMap(Collections.singletonMap("key", "new")); >+ >+ assertEquals(1, tracker.count); >+ >+ assertEquals(Collections.EMPTY_SET, tracker.event.diff.getAddedKeys()); >+ assertEquals(Collections.singleton("key"), tracker.event.diff >+ .getChangedKeys()); >+ assertEquals(Collections.EMPTY_SET, tracker.event.diff.getRemovedKeys()); >+ >+ assertEquals("old", tracker.event.diff.getOldValue("key")); >+ assertEquals("new", tracker.event.diff.getNewValue("key")); >+ } >+ >+} >#P org.eclipse.core.databinding.beans >Index: src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableMap.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableMap.java,v >retrieving revision 1.5 >diff -u -r1.5 JavaBeanObservableMap.java >--- src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableMap.java 17 Oct 2008 16:44:23 -0000 1.5 >+++ src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableMap.java 7 Nov 2008 01:59:41 -0000 >@@ -8,7 +8,7 @@ > * Contributors: > * IBM Corporation - initial API and implementation > * Brad Reynolds - bug 171616 >- * Matthew hall - bugs 223164, 241585, 226289 >+ * Matthew hall - bugs 223164, 241585, 226289, 246103 > *******************************************************************************/ > > package org.eclipse.core.internal.databinding.beans; >@@ -16,12 +16,15 @@ > import java.beans.PropertyChangeListener; > import java.beans.PropertyDescriptor; > import java.lang.reflect.Method; >+import java.util.HashMap; >+import java.util.Map; > > import org.eclipse.core.databinding.beans.IBeanObservable; > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.map.ComputedObservableMap; > import org.eclipse.core.databinding.observable.set.IObservableSet; > import org.eclipse.core.databinding.util.Policy; >+import org.eclipse.core.internal.databinding.Util; > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.Status; > >@@ -39,9 +42,19 @@ > if (!updating) { > getRealm().exec(new Runnable() { > public void run() { >- fireMapChange(Diffs.createMapDiffSingleChange( >- event.getSource(), event.getOldValue(), event >- .getNewValue())); >+ Object source = event.getSource(); >+ Object oldValue = event.getOldValue(); >+ Object newValue = event.getNewValue(); >+ if (oldValue == null && newValue == null) { >+ oldValue = cachedValues.get(new IdentityWrapper( >+ source)); >+ newValue = doGet(source); >+ } >+ cachedValues.put(new IdentityWrapper(source), newValue); >+ if (!Util.equals(oldValue, newValue)) { >+ fireMapChange(Diffs.createMapDiffSingleChange( >+ source, oldValue, newValue)); >+ } > } > }); > } >@@ -54,6 +67,9 @@ > > private boolean attachListeners; > >+ // Applicable only while hasListeners() == true >+ private Map cachedValues; >+ > /** > * @param domain > * @param propertyDescriptor >@@ -80,14 +96,31 @@ > } > } > >+ protected void firstListenerAdded() { >+ if (attachListeners) { >+ cachedValues = new HashMap(); >+ } >+ super.firstListenerAdded(); >+ } >+ >+ protected void lastListenerRemoved() { >+ super.lastListenerRemoved(); >+ if (attachListeners) { >+ cachedValues = null; >+ } >+ } >+ > protected void hookListener(Object domainElement) { > if (attachListeners && domainElement != null) { > listenerSupport.hookListener(domainElement); >+ cachedValues.put(new IdentityWrapper(domainElement), >+ doGet(domainElement)); > } > } > > protected void unhookListener(Object domainElement) { > if (attachListeners && domainElement != null) { >+ cachedValues.remove(new IdentityWrapper(domainElement)); > listenerSupport.unhookListener(domainElement); > } > } >@@ -113,9 +146,28 @@ > protected Object doPut(Object key, Object value) { > try { > Object oldValue = get(key); >- propertyDescriptor.getWriteMethod().invoke(key, >- new Object[] { value }); >- keySet().add(key); >+ if (!Util.equals(oldValue, value)) { >+ Method writeMethod = propertyDescriptor.getWriteMethod(); >+ if (!writeMethod.isAccessible()) { >+ writeMethod.setAccessible(true); >+ } >+ writeMethod.invoke(key, new Object[] { value }); >+ } >+ >+ if (hasListeners()) { >+ // oldValue contains the live value which may be different from >+ // the cached value if the bean does not have listener API or >+ // does not fire events properly. For consistency we want to >+ // provide the cached value as the old value, rather than the >+ // live value so that consumers that hook/unhook listeners can >+ // do so without maintaining caches of their own. >+ Object newValue = doGet(key); >+ oldValue = cachedValues.put(new IdentityWrapper(key), newValue); >+ >+ if (!Util.equals(oldValue, newValue)) { >+ fireSingleChange(key, oldValue, newValue); >+ } >+ } > return oldValue; > } catch (Exception e) { > Policy.getLog().log( >Index: src/org/eclipse/core/internal/databinding/beans/JavaBeanPropertyObservableMap.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanPropertyObservableMap.java,v >retrieving revision 1.3 >diff -u -r1.3 JavaBeanPropertyObservableMap.java >--- src/org/eclipse/core/internal/databinding/beans/JavaBeanPropertyObservableMap.java 26 Oct 2008 13:06:52 -0000 1.3 >+++ src/org/eclipse/core/internal/databinding/beans/JavaBeanPropertyObservableMap.java 7 Nov 2008 01:59:41 -0000 >@@ -7,7 +7,7 @@ > * > * Contributors: > * Matthew Hall - initial API and implementation (bug 221704) >- * Matthew Hall - bug 223164, 226289, 244098 >+ * Matthew Hall - bug 223164, 226289, 244098, 246103 > *******************************************************************************/ > > package org.eclipse.core.internal.databinding.beans; >@@ -84,11 +84,18 @@ > if (!updating) { > getRealm().exec(new Runnable() { > public void run() { >- Map oldValue = wrappedMap; >- Map newValue = (Map) event.getNewValue(); >- wrappedMap = new HashMap(newValue); >- >- fireMapChange(Diffs.computeMapDiff(oldValue, newValue)); >+ Map oldMap = (Map) event.getOldValue(); >+ Map newMap = (Map) event.getNewValue(); >+ if (oldMap == null && newMap == null) { >+ oldMap = wrappedMap; >+ newMap = getMap(); >+ } >+ >+ if (!Util.equals(oldMap, newMap)) { >+ wrappedMap = new HashMap(newMap); >+ fireMapChange(Diffs.computeMapDiff(oldMap, >+ newMap)); >+ } > } > }); > } >@@ -161,10 +168,11 @@ > checkRealm(); > updating = true; > try { >+ boolean add = !wrappedMap.containsKey(key); > Object result = wrappedMap.put(key, value); > if (!Util.equals(result, value)) { > setMap(); >- if (result == null) { >+ if (add) { > fireMapChange(Diffs.createMapDiffSingleAdd(key, value)); > } else { > fireMapChange(Diffs.createMapDiffSingleChange(key, result, >@@ -187,8 +195,9 @@ > Map.Entry entry = (Entry) it.next(); > Object key = entry.getKey(); > Object newValue = entry.getValue(); >+ boolean add = !wrappedMap.containsKey(key); > Object oldValue = wrappedMap.put(key, newValue); >- if (oldValue == null) { >+ if (add) { > addedKeys.add(key); > } else if (!Util.equals(oldValue, newValue)) { > changes.put(key, oldValue); >@@ -207,13 +216,14 @@ > > public Object remove(Object key) { > checkRealm(); >+ if (!wrappedMap.containsKey(key)) { >+ return null; >+ } > updating = true; > try { > Object result = wrappedMap.remove(key); >- if (result!=null) { >- setMap(); >- fireMapChange(Diffs.createMapDiffSingleRemove(key, result)); >- } >+ setMap(); >+ fireMapChange(Diffs.createMapDiffSingleRemove(key, result)); > return result; > } finally { > updating = false; >Index: src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.java,v >retrieving revision 1.2 >diff -u -r1.2 JavaBeanObservableValue.java >--- src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.java 24 Mar 2008 19:13:25 -0000 1.2 >+++ src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableValue.java 7 Nov 2008 01:59:41 -0000 >@@ -9,6 +9,7 @@ > * IBM Corporation - initial API and implementation > * Brad Reynolds - bug 164653 > * Brad Reynolds - bug 164134, 171616 >+ * Matthew Hall - bug 246103 > *******************************************************************************/ > package org.eclipse.core.internal.databinding.beans; > >@@ -23,7 +24,6 @@ > import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.Realm; > import org.eclipse.core.databinding.observable.value.AbstractObservableValue; >-import org.eclipse.core.databinding.observable.value.ValueDiff; > import org.eclipse.core.databinding.util.Policy; > import org.eclipse.core.internal.databinding.Util; > import org.eclipse.core.runtime.IStatus; >@@ -42,6 +42,9 @@ > > private boolean attachListeners; > >+ // Applicable only while hasListeners() == true >+ private Object cachedValue; >+ > /** > * @param realm > * @param object >@@ -70,25 +73,41 @@ > if (!attachListeners) { > return; > } >- >- PropertyChangeListener listener = new PropertyChangeListener() { >- public void propertyChange(java.beans.PropertyChangeEvent event) { >- if (!updating) { >- final ValueDiff diff = Diffs.createValueDiff(event.getOldValue(), >- event.getNewValue()); >- getRealm().exec(new Runnable(){ >- public void run() { >- fireValueChange(diff); >- }}); >- } >- } >- }; >- >+ > if (listenerSupport == null) { >- listenerSupport = new ListenerSupport(listener, propertyDescriptor.getName()); >+ PropertyChangeListener listener = new PropertyChangeListener() { >+ public void propertyChange( >+ final java.beans.PropertyChangeEvent event) { >+ if (!updating) { >+ getRealm().exec(new Runnable() { >+ public void run() { >+ Object oldValue = event.getOldValue(); >+ Object newValue = event.getNewValue(); >+ if (oldValue == null && newValue == null) { >+ // this condition is provided for in the >+ // bean spec, >+ // and indicates that an unknown change >+ // occured. >+ >+ oldValue = cachedValue; >+ newValue = doGetValue(); >+ } >+ cachedValue = newValue; >+ if (!Util.equals(oldValue, newValue)) { >+ fireValueChange(Diffs.createValueDiff( >+ oldValue, newValue)); >+ } >+ } >+ }); >+ } >+ } >+ }; >+ listenerSupport = new ListenerSupport(listener, propertyDescriptor >+ .getName()); > } > > listenerSupport.hookListener(object); >+ cachedValue = doGetValue(); > } > > public void doSetValue(Object value) { >@@ -96,16 +115,28 @@ > try { > Object oldValue = doGetValue(); > >- if (Util.equals(oldValue, value)) { >- return; >+ if (!Util.equals(oldValue, value)) { >+ Method writeMethod = propertyDescriptor.getWriteMethod(); >+ if (!writeMethod.isAccessible()) { >+ writeMethod.setAccessible(true); >+ } >+ writeMethod.invoke(object, new Object[] { value }); > } > >- Method writeMethod = propertyDescriptor.getWriteMethod(); >- if (!writeMethod.isAccessible()) { >- writeMethod.setAccessible(true); >+ if (hasListeners()) { >+ // oldValue contains the live value which may be different from >+ // the cached value if the bean does not have listener API or >+ // does not fire events properly. For consistency we want to >+ // provide the cached value as the old value, rather than the >+ // live value so that consumers that hook/unhook listeners can >+ // do so without maintaining caches of their own. >+ oldValue = cachedValue; >+ cachedValue = doGetValue(); >+ if (!Util.equals(oldValue, cachedValue)) { >+ fireValueChange(Diffs >+ .createValueDiff(oldValue, cachedValue)); >+ } > } >- writeMethod.invoke(object, new Object[] { value }); >- fireValueChange(Diffs.createValueDiff(oldValue, doGetValue())); > } catch (InvocationTargetException e) { > /* > * InvocationTargetException wraps any exception thrown by the >@@ -165,6 +196,7 @@ > } > > private void unhookListener() { >+ cachedValue = null; > if (listenerSupport != null) { > listenerSupport.dispose(); > listenerSupport = null;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 246103
: 117279 |
117280