Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Hall2009-01-24 23:42:58 +0000
committerMatthew Hall2009-01-24 23:42:58 +0000
commite59897c0e41b5f9a235952756fb2d3a4581a7fb6 (patch)
tree371ae11d2d4538d774b0709cd7138d0816fd2ed4 /bundles/org.eclipse.core.databinding/src/org/eclipse
parent7fd0132b2f61f92953408a92423c9e5e65d38714 (diff)
downloadorg.eclipse.e4.databinding-e59897c0e41b5f9a235952756fb2d3a4581a7fb6.tar.gz
org.eclipse.e4.databinding-e59897c0e41b5f9a235952756fb2d3a4581a7fb6.tar.xz
org.eclipse.e4.databinding-e59897c0e41b5f9a235952756fb2d3a4581a7fb6.zip
FIXED - bug 262269: [DataBinding] Need IdentitySet, IdentityMap and IdentityObservableSet classes
https://bugs.eclipse.org/bugs/show_bug.cgi?id=262269
Diffstat (limited to 'bundles/org.eclipse.core.databinding/src/org/eclipse')
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/ObservableTracker.java67
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentityMap.java406
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentitySet.java172
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/IdentityObservableSet.java167
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java22
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java55
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java5
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java37
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java49
-rw-r--r--bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java15
10 files changed, 842 insertions, 153 deletions
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/ObservableTracker.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/ObservableTracker.java
index 3f228939..91f1c5fb 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/ObservableTracker.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/databinding/observable/ObservableTracker.java
@@ -7,15 +7,13 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Matthew Hall - bugs 210115, 146397, 249526
+ * Matthew Hall - bugs 210115, 146397, 249526, 262269
*******************************************************************************/
package org.eclipse.core.databinding.observable;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.Set;
-import org.eclipse.core.internal.databinding.IdentityWrapper;
+import org.eclipse.core.internal.databinding.IdentitySet;
import org.eclipse.core.runtime.Assert;
/**
@@ -96,7 +94,7 @@ public class ObservableTracker {
IStaleListener lastStaleListener = (IStaleListener) currentStaleListener
.get();
- Set observableSet = new HashSet();
+ Set observableSet = new IdentitySet();
// Push the new listeners to the top of the stack
currentGetterCalledSet.set(observableSet);
currentChangeListener.set(changeListener);
@@ -111,14 +109,8 @@ public class ObservableTracker {
currentStaleListener.set(lastStaleListener);
}
- int i = 0;
- IObservable[] result = new IObservable[observableSet.size()];
- for (Iterator it = observableSet.iterator(); it.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- result[i++] = (IObservable) wrapper.unwrap();
- }
-
- return result;
+ return (IObservable[]) observableSet
+ .toArray(new IObservable[observableSet.size()]);
}
/**
@@ -135,7 +127,7 @@ public class ObservableTracker {
public static IObservable[] runAndCollect(Runnable runnable) {
Set lastObservableCreatedSet = (Set) currentObservableCreatedSet.get();
- Set observableSet = new HashSet();
+ Set observableSet = new IdentitySet();
// Push the new listeners to the top of the stack
currentObservableCreatedSet.set(observableSet);
try {
@@ -146,14 +138,8 @@ public class ObservableTracker {
currentObservableCreatedSet.set(lastObservableCreatedSet);
}
- int i = 0;
- IObservable[] result = new IObservable[observableSet.size()];
- for (Iterator it = observableSet.iterator(); it.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- result[i++] = (IObservable) wrapper.unwrap();
- }
-
- return result;
+ return (IObservable[]) observableSet
+ .toArray(new IObservable[observableSet.size()]);
}
/**
@@ -215,26 +201,17 @@ public class ObservableTracker {
Assert.isTrue(false, "Getter called outside realm of observable " //$NON-NLS-1$
+ toString(observable));
- Set lastGetterCalledSet = (Set) currentGetterCalledSet.get();
- if (lastGetterCalledSet == null) {
- return;
- }
- IChangeListener lastChangeListener = (IChangeListener) currentChangeListener
- .get();
- IStaleListener lastStaleListener = (IStaleListener) currentStaleListener
- .get();
-
- boolean added = false;
- if (lastGetterCalledSet != null) {
- added = lastGetterCalledSet.add(new IdentityWrapper(observable));
- }
-
- // If anyone is listening for observable usage...
- if (added && lastChangeListener != null) {
- observable.addChangeListener(lastChangeListener);
- }
- if (added && lastStaleListener != null) {
- observable.addStaleListener(lastStaleListener);
+ Set getterCalledSet = (Set) currentGetterCalledSet.get();
+ if (getterCalledSet != null && getterCalledSet.add(observable)) {
+ // If anyone is listening for observable usage...
+ IChangeListener changeListener = (IChangeListener) currentChangeListener
+ .get();
+ if (changeListener != null)
+ observable.addChangeListener(changeListener);
+ IStaleListener staleListener = (IStaleListener) currentStaleListener
+ .get();
+ if (staleListener != null)
+ observable.addStaleListener(staleListener);
}
}
@@ -246,9 +223,9 @@ public class ObservableTracker {
* @since 1.2
*/
public static void observableCreated(IObservable observable) {
- Set lastObservableCreatedSet = (Set) currentObservableCreatedSet.get();
- if (lastObservableCreatedSet != null) {
- lastObservableCreatedSet.add(new IdentityWrapper(observable));
+ Set observableCreatedSet = (Set) currentObservableCreatedSet.get();
+ if (observableCreatedSet != null) {
+ observableCreatedSet.add(observable);
}
}
}
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentityMap.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentityMap.java
new file mode 100644
index 00000000..97c92538
--- /dev/null
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentityMap.java
@@ -0,0 +1,406 @@
+/*******************************************************************************
+ * 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 215531)
+ * Matthew Hall - bug 228125
+ * (through ViewerElementMap.java)
+ * Matthew Hall - bug 262269
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * A {@link Map} whose keys are added, removed and compared by identity. The
+ * keys in the map are compared using <code>==</code> instead of
+ * {@link #equals(Object)}.
+ * <p>
+ * This class is <i>not</i> a strict implementation the {@link Map} interface.
+ * It intentionally violates the {@link Map} contract, which requires the use of
+ * {@link #equals(Object)} when comparing keys.
+ *
+ * @since 1.2
+ */
+public class IdentityMap implements Map {
+ private Map wrappedMap;
+
+ /**
+ * Constructs an IdentityMap.
+ */
+ public IdentityMap() {
+ this.wrappedMap = new HashMap();
+ }
+
+ /**
+ * Constructs an IdentityMap containing all the entries in the specified
+ * map.
+ *
+ * @param map
+ * the map whose entries are to be added to this map.
+ */
+ public IdentityMap(Map map) {
+ this();
+ Assert.isNotNull(map);
+ putAll(map);
+ }
+
+ public void clear() {
+ wrappedMap.clear();
+ }
+
+ public boolean containsKey(Object key) {
+ return wrappedMap.containsKey(new IdentityWrapper(key));
+ }
+
+ public boolean containsValue(Object value) {
+ return wrappedMap.containsValue(value);
+ }
+
+ public Set entrySet() {
+ final Set wrappedEntrySet = wrappedMap.entrySet();
+ return new Set() {
+ public boolean add(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean addAll(Collection c) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear() {
+ wrappedEntrySet.clear();
+ }
+
+ public boolean contains(Object o) {
+ for (Iterator iterator = iterator(); iterator.hasNext();)
+ if (iterator.next().equals(o))
+ return true;
+ return false;
+ }
+
+ public boolean containsAll(Collection c) {
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ if (!contains(iterator.next()))
+ return false;
+ return true;
+ }
+
+ public boolean isEmpty() {
+ return wrappedEntrySet.isEmpty();
+ }
+
+ public Iterator iterator() {
+ final Iterator wrappedIterator = wrappedEntrySet.iterator();
+ return new Iterator() {
+ public boolean hasNext() {
+ return wrappedIterator.hasNext();
+ }
+
+ public Object next() {
+ final Map.Entry wrappedEntry = (Map.Entry) wrappedIterator
+ .next();
+ return new Map.Entry() {
+ public Object getKey() {
+ return ((IdentityWrapper) wrappedEntry.getKey())
+ .unwrap();
+ }
+
+ public Object getValue() {
+ return wrappedEntry.getValue();
+ }
+
+ public Object setValue(Object value) {
+ return wrappedEntry.setValue(value);
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (obj == null || !(obj instanceof Map.Entry))
+ return false;
+ Map.Entry that = (Map.Entry) obj;
+ return this.getKey() == that.getKey()
+ && Util.equals(this.getValue(), that
+ .getValue());
+ }
+
+ public int hashCode() {
+ return wrappedEntry.hashCode();
+ }
+ };
+ }
+
+ public void remove() {
+ wrappedIterator.remove();
+ }
+ };
+ }
+
+ public boolean remove(Object o) {
+ final Map.Entry unwrappedEntry = (Map.Entry) o;
+ final IdentityWrapper wrappedKey = new IdentityWrapper(
+ unwrappedEntry.getKey());
+ Map.Entry wrappedEntry = new Map.Entry() {
+ public Object getKey() {
+ return wrappedKey;
+ }
+
+ public Object getValue() {
+ return unwrappedEntry.getValue();
+ }
+
+ public Object setValue(Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (obj == null || !(obj instanceof Map.Entry))
+ return false;
+ Map.Entry that = (Map.Entry) obj;
+ return Util.equals(wrappedKey, that.getKey())
+ && Util
+ .equals(this.getValue(), that
+ .getValue());
+ }
+
+ public int hashCode() {
+ return wrappedKey.hashCode()
+ ^ (getValue() == null ? 0 : getValue()
+ .hashCode());
+ }
+ };
+ return wrappedEntrySet.remove(wrappedEntry);
+ }
+
+ public boolean removeAll(Collection c) {
+ boolean changed = false;
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ changed |= remove(iterator.next());
+ return changed;
+ }
+
+ public boolean retainAll(Collection c) {
+ boolean changed = false;
+ Object[] toRetain = c.toArray();
+ outer: for (Iterator iterator = iterator(); iterator.hasNext();) {
+ Object entry = iterator.next();
+ for (int i = 0; i < toRetain.length; i++)
+ if (entry.equals(toRetain[i]))
+ continue outer;
+ iterator.remove();
+ changed = true;
+ }
+ return changed;
+ }
+
+ public int size() {
+ return wrappedEntrySet.size();
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[size()]);
+ }
+
+ public Object[] toArray(Object[] a) {
+ int size = size();
+ if (a.length < size) {
+ a = (Object[]) Array.newInstance(a.getClass()
+ .getComponentType(), size);
+ }
+ int i = 0;
+ for (Iterator iterator = iterator(); iterator.hasNext();) {
+ a[i] = iterator.next();
+ i++;
+ }
+ return a;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (obj == null || !(obj instanceof Set))
+ return false;
+ Set that = (Set) obj;
+ return this.size() == that.size() && containsAll(that);
+ }
+
+ public int hashCode() {
+ return wrappedEntrySet.hashCode();
+ }
+ };
+ }
+
+ public Object get(Object key) {
+ return wrappedMap.get(new IdentityWrapper(key));
+ }
+
+ public boolean isEmpty() {
+ return wrappedMap.isEmpty();
+ }
+
+ public Set keySet() {
+ final Set wrappedKeySet = wrappedMap.keySet();
+ return new Set() {
+ public boolean add(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean addAll(Collection c) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear() {
+ wrappedKeySet.clear();
+ }
+
+ public boolean contains(Object o) {
+ return wrappedKeySet.contains(new IdentityWrapper(o));
+ }
+
+ public boolean containsAll(Collection c) {
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ if (!wrappedKeySet.contains(new IdentityWrapper(iterator
+ .next())))
+ return false;
+ return true;
+ }
+
+ public boolean isEmpty() {
+ return wrappedKeySet.isEmpty();
+ }
+
+ public Iterator iterator() {
+ final Iterator wrappedIterator = wrappedKeySet.iterator();
+ return new Iterator() {
+ public boolean hasNext() {
+ return wrappedIterator.hasNext();
+ }
+
+ public Object next() {
+ return ((IdentityWrapper) wrappedIterator.next())
+ .unwrap();
+ }
+
+ public void remove() {
+ wrappedIterator.remove();
+ }
+ };
+ }
+
+ public boolean remove(Object o) {
+ return wrappedKeySet.remove(new IdentityWrapper(o));
+ }
+
+ public boolean removeAll(Collection c) {
+ boolean changed = false;
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ changed |= wrappedKeySet.remove(new IdentityWrapper(
+ iterator.next()));
+ return changed;
+ }
+
+ public boolean retainAll(Collection c) {
+ boolean changed = false;
+ Object[] toRetain = c.toArray();
+ outer: for (Iterator iterator = iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ for (int i = 0; i < toRetain.length; i++)
+ if (element == toRetain[i])
+ continue outer;
+ // element not contained in collection, remove.
+ remove(element);
+ changed = true;
+ }
+ return changed;
+ }
+
+ public int size() {
+ return wrappedKeySet.size();
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[wrappedKeySet.size()]);
+ }
+
+ public Object[] toArray(Object[] a) {
+ int size = wrappedKeySet.size();
+ IdentityWrapper[] wrappedArray = (IdentityWrapper[]) wrappedKeySet
+ .toArray(new IdentityWrapper[size]);
+ Object[] result = a;
+ if (a.length < size) {
+ result = (Object[]) Array.newInstance(a.getClass()
+ .getComponentType(), size);
+ }
+ for (int i = 0; i < size; i++)
+ result[i] = wrappedArray[i].unwrap();
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (obj == null || !(obj instanceof Set))
+ return false;
+ Set that = (Set) obj;
+ return this.size() == that.size() && containsAll(that);
+ }
+
+ public int hashCode() {
+ return wrappedKeySet.hashCode();
+ }
+ };
+ }
+
+ public Object put(Object key, Object value) {
+ return wrappedMap.put(new IdentityWrapper(key), value);
+ }
+
+ public void putAll(Map other) {
+ for (Iterator iterator = other.entrySet().iterator(); iterator
+ .hasNext();) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ wrappedMap.put(new IdentityWrapper(entry.getKey()), entry
+ .getValue());
+ }
+ }
+
+ public Object remove(Object key) {
+ return wrappedMap.remove(new IdentityWrapper(key));
+ }
+
+ public int size() {
+ return wrappedMap.size();
+ }
+
+ public Collection values() {
+ return wrappedMap.values();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (obj == null || !(obj instanceof Map))
+ return false;
+ Map that = (Map) obj;
+ return this.entrySet().equals(that.entrySet());
+ }
+
+ public int hashCode() {
+ return wrappedMap.hashCode();
+ }
+}
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentitySet.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentitySet.java
new file mode 100644
index 00000000..f7f0079e
--- /dev/null
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/IdentitySet.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * 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 215531)
+ * Matthew Hall - bug 124684
+ * (through ViewerElementSet.java)
+ * Matthew Hall - bug 262269
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A {@link Set} of elements where elements are added, removed and compared by
+ * identity. Elements of the set are compared using <code>==</code> instead of
+ * {@link #equals(Object)}.
+ * <p>
+ * This class is <i>not</i> a strict implementation the {@link Set} interface.
+ * It intentionally violates the {@link Set} contract, which requires the use of
+ * {@link #equals(Object)} when comparing elements.
+ *
+ * @since 1.2
+ */
+public class IdentitySet implements Set {
+ private final Set wrappedSet;
+
+ /**
+ * Constructs an IdentitySet.
+ */
+ public IdentitySet() {
+ this.wrappedSet = new HashSet();
+ }
+
+ /**
+ * Constructs an IdentitySet containing all the unique instances in the
+ * specified collection.
+ *
+ * @param collection
+ * the collection whose elements are to be added to this set.
+ */
+ public IdentitySet(Collection collection) {
+ this();
+ addAll(collection);
+ }
+
+ public boolean add(Object o) {
+ return wrappedSet.add(new IdentityWrapper(o));
+ }
+
+ public boolean addAll(Collection c) {
+ boolean changed = false;
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ changed |= wrappedSet.add(new IdentityWrapper(iterator.next()));
+ return changed;
+ }
+
+ public void clear() {
+ wrappedSet.clear();
+ }
+
+ public boolean contains(Object o) {
+ return wrappedSet.contains(new IdentityWrapper(o));
+ }
+
+ public boolean containsAll(Collection c) {
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ if (!wrappedSet.contains(new IdentityWrapper(iterator.next())))
+ return false;
+ return true;
+ }
+
+ public boolean isEmpty() {
+ return wrappedSet.isEmpty();
+ }
+
+ public Iterator iterator() {
+ final Iterator wrappedIterator = wrappedSet.iterator();
+ return new Iterator() {
+ public boolean hasNext() {
+ return wrappedIterator.hasNext();
+ }
+
+ public Object next() {
+ return ((IdentityWrapper) wrappedIterator.next()).unwrap();
+ }
+
+ public void remove() {
+ wrappedIterator.remove();
+ }
+ };
+ }
+
+ public boolean remove(Object o) {
+ return wrappedSet.remove(new IdentityWrapper(o));
+ }
+
+ public boolean removeAll(Collection c) {
+ boolean changed = false;
+ for (Iterator iterator = c.iterator(); iterator.hasNext();)
+ changed |= remove(iterator.next());
+ return changed;
+ }
+
+ public boolean retainAll(Collection c) {
+ // Have to do this the slow way to ensure correct comparisons. i.e.
+ // cannot delegate to c.contains(it) since we can't be sure will
+ // compare elements the way we want.
+ boolean changed = false;
+ Object[] retainAll = c.toArray();
+ outer: for (Iterator iterator = iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ for (int i = 0; i < retainAll.length; i++) {
+ if (element == retainAll[i]) {
+ continue outer;
+ }
+ }
+ iterator.remove();
+ changed = true;
+ }
+ return changed;
+ }
+
+ public int size() {
+ return wrappedSet.size();
+ }
+
+ public Object[] toArray() {
+ return toArray(new Object[wrappedSet.size()]);
+ }
+
+ public Object[] toArray(Object[] a) {
+ int size = wrappedSet.size();
+ IdentityWrapper[] wrappedArray = (IdentityWrapper[]) wrappedSet
+ .toArray(new IdentityWrapper[size]);
+ Object[] result = a;
+ if (a.length < size) {
+ result = (Object[]) Array.newInstance(a.getClass()
+ .getComponentType(), size);
+ }
+ for (int i = 0; i < size; i++)
+ result[i] = wrappedArray[i].unwrap();
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj == this)
+ return true;
+ if (!(obj instanceof Set))
+ return false;
+ Set that = (Set) obj;
+ return size() == that.size() && containsAll(that);
+ }
+
+ public int hashCode() {
+ int hash = 0;
+ for (Iterator iterator = iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ hash += element == null ? 0 : element.hashCode();
+ }
+ return hash;
+ }
+}
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/IdentityObservableSet.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/IdentityObservableSet.java
new file mode 100644
index 00000000..ca4c6ae7
--- /dev/null
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/IdentityObservableSet.java
@@ -0,0 +1,167 @@
+/*******************************************************************************
+ * 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 215531)
+ * Matthew Hall - bug 230267
+ * (through ObservableViewerElementSet.java)
+ * Matthew Hall - bug 262269
+ ******************************************************************************/
+
+package org.eclipse.core.internal.databinding.observable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.core.databinding.observable.Diffs;
+import org.eclipse.core.databinding.observable.Realm;
+import org.eclipse.core.databinding.observable.set.AbstractObservableSet;
+import org.eclipse.core.databinding.observable.set.IObservableSet;
+import org.eclipse.core.internal.databinding.IdentitySet;
+
+/**
+ * An {@link IObservableSet} of elements where elements are added, removed and
+ * compared by identity. Elements of the set are compared using <code>==</code>
+ * instead of {@link #equals(Object)}.
+ * <p>
+ * This class is <i>not</i> a strict implementation the {@link IObservableSet}
+ * interface. It intentionally violates the {@link Set} contract, which requires
+ * the use of {@link #equals(Object)} when comparing elements.
+ *
+ * @since 1.2
+ */
+public class IdentityObservableSet extends AbstractObservableSet {
+ private Set wrappedSet;
+ private Object elementType;
+
+ /**
+ * Constructs an IdentityObservableSet on the given {@link Realm}.
+ *
+ * @param realm
+ * the realm of the constructed set.
+ * @param elementType
+ * the element type of the constructed set.
+ */
+ public IdentityObservableSet(Realm realm, Object elementType) {
+ super(realm);
+
+ this.wrappedSet = new IdentitySet();
+ this.elementType = elementType;
+ }
+
+ protected Set getWrappedSet() {
+ return wrappedSet;
+ }
+
+ public Object getElementType() {
+ return elementType;
+ }
+
+ public Iterator iterator() {
+ getterCalled();
+ final Iterator wrappedIterator = wrappedSet.iterator();
+ return new Iterator() {
+ Object last;
+
+ public boolean hasNext() {
+ getterCalled();
+ return wrappedIterator.hasNext();
+ }
+
+ public Object next() {
+ getterCalled();
+ return last = wrappedIterator.next();
+ }
+
+ public void remove() {
+ getterCalled();
+ wrappedIterator.remove();
+ fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
+ Collections.singleton(last)));
+ }
+ };
+ }
+
+ public boolean add(Object o) {
+ getterCalled();
+ boolean changed = wrappedSet.add(o);
+ if (changed)
+ fireSetChange(Diffs.createSetDiff(Collections.singleton(o),
+ Collections.EMPTY_SET));
+ return changed;
+ }
+
+ public boolean addAll(Collection c) {
+ getterCalled();
+ Set additions = new IdentitySet();
+ for (Iterator iterator = c.iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ if (wrappedSet.add(element))
+ additions.add(element);
+ }
+ boolean changed = !additions.isEmpty();
+ if (changed)
+ fireSetChange(Diffs.createSetDiff(additions, Collections.EMPTY_SET));
+ return changed;
+ }
+
+ public boolean remove(Object o) {
+ getterCalled();
+ boolean changed = wrappedSet.remove(o);
+ if (changed)
+ fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
+ Collections.singleton(o)));
+ return changed;
+ }
+
+ public boolean removeAll(Collection c) {
+ getterCalled();
+ Set removals = new IdentitySet();
+ for (Iterator iterator = c.iterator(); iterator.hasNext();) {
+ Object element = iterator.next();
+ if (wrappedSet.remove(element))
+ removals.add(element);
+ }
+ boolean changed = !removals.isEmpty();
+ if (changed)
+ fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
+ return changed;
+ }
+
+ public boolean retainAll(Collection c) {
+ getterCalled();
+ Set removals = new IdentitySet();
+ Object[] toRetain = c.toArray();
+ outer: for (Iterator iterator = wrappedSet.iterator(); iterator
+ .hasNext();) {
+ Object element = iterator.next();
+ // Cannot rely on c.contains(element) because we must compare
+ // elements using IElementComparer.
+ for (int i = 0; i < toRetain.length; i++) {
+ if (element == toRetain[i])
+ continue outer;
+ }
+ iterator.remove();
+ removals.add(element);
+ }
+ boolean changed = !removals.isEmpty();
+ if (changed)
+ fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
+ return changed;
+ }
+
+ public void clear() {
+ getterCalled();
+ if (!wrappedSet.isEmpty()) {
+ Set removals = wrappedSet;
+ wrappedSet = new IdentitySet();
+ fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
+ }
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java
index 6324325e..7b0d4b25 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java
@@ -7,11 +7,11 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Matthew Hall - bug 262269
******************************************************************************/
package org.eclipse.core.internal.databinding.observable;
-import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.databinding.observable.ChangeEvent;
@@ -19,7 +19,7 @@ import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.IObservable;
import org.eclipse.core.databinding.observable.IStaleListener;
import org.eclipse.core.databinding.observable.StaleEvent;
-import org.eclipse.core.internal.databinding.IdentityWrapper;
+import org.eclipse.core.internal.databinding.IdentityMap;
/**
* @since 1.0
@@ -27,7 +27,7 @@ import org.eclipse.core.internal.databinding.IdentityWrapper;
*/
public class StalenessTracker {
- private Map staleMap = new HashMap();
+ private Map staleMap = new IdentityMap();
private int staleCount = 0;
@@ -65,8 +65,7 @@ public class StalenessTracker {
*/
public void processStalenessChange(IObservable child, boolean callback) {
boolean oldStale = staleCount > 0;
- IdentityWrapper wrappedChild = new IdentityWrapper(child);
- boolean oldChildStale = getOldChildStale(wrappedChild);
+ boolean oldChildStale = getOldChildStale(child);
boolean newChildStale = child.isStale();
if (oldChildStale != newChildStale) {
if (oldChildStale) {
@@ -74,7 +73,7 @@ public class StalenessTracker {
} else {
staleCount++;
}
- staleMap.put(wrappedChild, newChildStale ? Boolean.TRUE : Boolean.FALSE);
+ staleMap.put(child, newChildStale ? Boolean.TRUE : Boolean.FALSE);
}
boolean newStale = staleCount > 0;
if (callback && (newStale != oldStale)) {
@@ -83,10 +82,10 @@ public class StalenessTracker {
}
/**
- * @param wrappedChild
+ * @param child
*/
- private boolean getOldChildStale(IdentityWrapper wrappedChild) {
- Object oldChildValue = staleMap.get(wrappedChild);
+ private boolean getOldChildStale(IObservable child) {
+ Object oldChildValue = staleMap.get(child);
boolean oldChildStale = oldChildValue == null ? false
: ((Boolean) oldChildValue).booleanValue();
return oldChildStale;
@@ -110,12 +109,11 @@ public class StalenessTracker {
*/
public void removeObservable(IObservable observable) {
boolean oldStale = staleCount > 0;
- IdentityWrapper wrappedChild = new IdentityWrapper(observable);
- boolean oldChildStale = getOldChildStale(wrappedChild);
+ boolean oldChildStale = getOldChildStale(observable);
if (oldChildStale) {
staleCount--;
}
- staleMap.remove(wrappedChild);
+ staleMap.remove(observable);
observable.removeChangeListener(childListener);
observable.removeStaleListener(childListener);
boolean newStale = staleCount > 0;
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java
index 64ac6a11..db1d1634 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java
@@ -1,20 +1,19 @@
/*******************************************************************************
- * Copyright (c) 2009 IBM Corporation and others.
+ * Copyright (c) 2009 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:
- * IBM Corporation - initial API and implementation
+ * Matthew Hall - initial API and implementation (bug 194734)
+ * Matthew Hall - bug 262269
******************************************************************************/
package org.eclipse.core.internal.databinding.property.value;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -26,11 +25,10 @@ import org.eclipse.core.databinding.observable.map.MapChangeEvent;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
-import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.core.databinding.property.value.DelegatingValueProperty;
import org.eclipse.core.databinding.property.value.IValueProperty;
-import org.eclipse.core.internal.databinding.IdentityWrapper;
-import org.eclipse.core.internal.databinding.Util;
+import org.eclipse.core.internal.databinding.IdentityMap;
+import org.eclipse.core.internal.databinding.observable.IdentityObservableSet;
/**
* @since 3.3
@@ -50,8 +48,8 @@ abstract class DelegatingCache {
DelegateCache(IValueProperty delegate) {
this.delegate = delegate;
- this.masterElements = new WritableSet(realm, Collections.EMPTY_SET,
- elements.getElementType());
+ this.masterElements = new IdentityObservableSet(realm, elements
+ .getElementType());
this.masterElementValues = delegate.observeDetail(masterElements);
this.cachedValues = new HashMap();
@@ -62,22 +60,22 @@ abstract class DelegatingCache {
boolean wasEmpty = masterElements.isEmpty();
masterElements.add(masterElement);
- cachedValues.put(new IdentityWrapper(masterElement),
- masterElementValues.get(masterElement));
+ cachedValues.put(masterElement, masterElementValues
+ .get(masterElement));
if (wasEmpty)
delegateCaches.put(delegate, this);
}
void remove(Object masterElement) {
- cachedValues.remove(new IdentityWrapper(masterElement));
+ cachedValues.remove(masterElement);
masterElements.remove(masterElement);
if (cachedValues.isEmpty())
dispose();
}
Object get(Object masterElement) {
- return cachedValues.get(new IdentityWrapper(masterElement));
+ return cachedValues.get(masterElement);
}
Object put(Object masterElement, Object detailValue) {
@@ -98,11 +96,10 @@ abstract class DelegatingCache {
}
private void notifyIfChanged(Object masterElement) {
- Object oldValue = cachedValues.get(new IdentityWrapper(
- masterElement));
+ Object oldValue = cachedValues.get(masterElement);
Object newValue = masterElementValues.get(masterElement);
- if (!Util.equals(oldValue, newValue)) {
- cachedValues.put(new IdentityWrapper(masterElement), newValue);
+ if (oldValue != newValue) {
+ cachedValues.put(masterElement, newValue);
handleValueChange(masterElement, oldValue, newValue);
}
}
@@ -125,22 +122,20 @@ abstract class DelegatingCache {
this.realm = realm;
this.detailProperty = detailProperty;
- this.elements = new WritableSet(realm);
- this.delegateCaches = new HashMap();
+ this.elements = new IdentityObservableSet(realm, null);
+ this.delegateCaches = new IdentityMap();
elements.addSetChangeListener(new ISetChangeListener() {
public void handleSetChange(SetChangeEvent event) {
for (Iterator it = event.diff.getRemovals().iterator(); it
.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- Object element = wrapper.unwrap();
+ Object element = it.next();
getCache(element).remove(element);
}
for (Iterator it = event.diff.getAdditions().iterator(); it
.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- Object element = wrapper.unwrap();
+ Object element = it.next();
getCache(element).add(element);
}
}
@@ -163,7 +158,7 @@ abstract class DelegatingCache {
return getCache(element).put(element, value);
}
- boolean contains(Object value) {
+ boolean containsValue(Object value) {
for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) {
DelegateCache cache = (DelegateCache) it.next();
if (cache.containsValue(value))
@@ -172,20 +167,12 @@ abstract class DelegatingCache {
return false;
}
- private Set identitySet(Collection elements) {
- Set result = new HashSet();
- for (Iterator it = elements.iterator(); it.hasNext();) {
- result.add(new IdentityWrapper(it.next()));
- }
- return result;
- }
-
void addAll(Collection elements) {
- this.elements.addAll(identitySet(elements));
+ this.elements.addAll(elements);
}
void retainAll(Collection elements) {
- this.elements.retainAll(identitySet(elements));
+ this.elements.retainAll(elements);
}
abstract void handleValueChange(Object masterElement, Object oldValue,
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java
index ab56c145..f67c5742 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java
@@ -6,7 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Matthew Hall - initial API and implementation
+ * Matthew Hall - initial API and implementation (bug 194734)
+ * Matthew Hall - bug 262269
******************************************************************************/
package org.eclipse.core.internal.databinding.property.value;
@@ -130,7 +131,7 @@ public class ListDelegatingValueObservableList extends AbstractObservableList
public boolean contains(Object o) {
getterCalled();
- return cache.contains(o);
+ return cache.containsValue(o);
}
public boolean isEmpty() {
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java
index aebbb311..4076a861 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Matthew Hall - initial API and implementation (bug 194734)
+ * Matthew Hall - bug 262269
******************************************************************************/
package org.eclipse.core.internal.databinding.property.value;
@@ -14,8 +15,6 @@ package org.eclipse.core.internal.databinding.property.value;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
@@ -35,15 +34,16 @@ import org.eclipse.core.databinding.observable.list.ListDiffEntry;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
-import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.core.databinding.property.INativePropertyListener;
import org.eclipse.core.databinding.property.IProperty;
import org.eclipse.core.databinding.property.IPropertyObservable;
import org.eclipse.core.databinding.property.ISimplePropertyListener;
import org.eclipse.core.databinding.property.SimplePropertyEvent;
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
-import org.eclipse.core.internal.databinding.IdentityWrapper;
+import org.eclipse.core.internal.databinding.IdentityMap;
+import org.eclipse.core.internal.databinding.IdentitySet;
import org.eclipse.core.internal.databinding.Util;
+import org.eclipse.core.internal.databinding.observable.IdentityObservableSet;
/**
* @since 1.2
@@ -67,11 +67,7 @@ public class ListSimpleValueObservableList extends AbstractObservableList
}
private void updateKnownElements() {
- Set identityKnownElements = new HashSet();
- for (Iterator it = masterList.iterator(); it.hasNext();) {
- identityKnownElements.add(new IdentityWrapper(it.next()));
- }
-
+ Set identityKnownElements = new IdentitySet(masterList);
knownMasterElements.retainAll(identityKnownElements);
knownMasterElements.addAll(identityKnownElements);
}
@@ -123,29 +119,25 @@ public class ListSimpleValueObservableList extends AbstractObservableList
}
protected void firstListenerAdded() {
- knownMasterElements = new WritableSet(getRealm());
- cachedValues = new HashMap();
+ knownMasterElements = new IdentityObservableSet(getRealm(), null);
+ cachedValues = new IdentityMap();
knownMasterElements.addSetChangeListener(new ISetChangeListener() {
public void handleSetChange(SetChangeEvent event) {
for (Iterator it = event.diff.getRemovals().iterator(); it
.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- Object key = wrapper.unwrap();
+ Object key = it.next();
detailProperty.removeListener(key, detailListener);
- cachedValues.remove(wrapper);
+ cachedValues.remove(key);
}
for (Iterator it = event.diff.getAdditions().iterator(); it
.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- Object key = wrapper.unwrap();
- cachedValues.put(wrapper, detailProperty.getValue(key));
+ Object key = it.next();
+ cachedValues.put(key, detailProperty.getValue(key));
detailProperty.addListener(key, detailListener);
}
}
});
- for (Iterator it = masterList.iterator(); it.hasNext();) {
- knownMasterElements.add(new IdentityWrapper(it.next()));
- }
+ knownMasterElements.addAll(masterList);
masterList.addListChangeListener(masterListener);
masterList.addStaleListener(staleListener);
@@ -360,11 +352,10 @@ public class ListSimpleValueObservableList extends AbstractObservableList
private void notifyIfChanged(Object masterElement) {
if (cachedValues != null) {
- Object oldValue = cachedValues.get(new IdentityWrapper(
- masterElement));
+ Object oldValue = cachedValues.get(masterElement);
Object newValue = detailProperty.getValue(masterElement);
if (!Util.equals(oldValue, newValue)) {
- cachedValues.put(new IdentityWrapper(masterElement), newValue);
+ cachedValues.put(masterElement, newValue);
fireListChange(indicesOf(masterElement), oldValue, newValue);
}
}
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java
index ee4ba4b3..48729b9d 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java
@@ -7,14 +7,13 @@
*
* Contributors:
* Matthew Hall - initial API and implementation (bug 194734)
+ * Matthew Hall - bug 262269
******************************************************************************/
package org.eclipse.core.internal.databinding.property.value;
import java.util.AbstractSet;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -31,15 +30,16 @@ import org.eclipse.core.databinding.observable.map.MapDiff;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.observable.set.ISetChangeListener;
import org.eclipse.core.databinding.observable.set.SetChangeEvent;
-import org.eclipse.core.databinding.observable.set.WritableSet;
import org.eclipse.core.databinding.property.INativePropertyListener;
import org.eclipse.core.databinding.property.IProperty;
import org.eclipse.core.databinding.property.IPropertyObservable;
import org.eclipse.core.databinding.property.ISimplePropertyListener;
import org.eclipse.core.databinding.property.SimplePropertyEvent;
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
-import org.eclipse.core.internal.databinding.IdentityWrapper;
+import org.eclipse.core.internal.databinding.IdentityMap;
+import org.eclipse.core.internal.databinding.IdentitySet;
import org.eclipse.core.internal.databinding.Util;
+import org.eclipse.core.internal.databinding.observable.IdentityObservableSet;
/**
* @since 1.2
@@ -65,18 +65,14 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap
}
private void updateKnownValues() {
- Set identityKnownValues = new HashSet();
- for (Iterator it = masterMap.values().iterator(); it.hasNext();) {
- identityKnownValues.add(new IdentityWrapper(it.next()));
- }
-
- knownMasterValues.retainAll(identityKnownValues);
- knownMasterValues.addAll(identityKnownValues);
+ Set knownValues = new IdentitySet(masterMap.values());
+ knownMasterValues.retainAll(knownValues);
+ knownMasterValues.addAll(knownValues);
}
private MapDiff convertDiff(MapDiff diff) {
- Map oldValues = new HashMap();
- Map newValues = new HashMap();
+ Map oldValues = new IdentityMap();
+ Map newValues = new IdentityMap();
Set addedKeys = diff.getAddedKeys();
for (Iterator it = addedKeys.iterator(); it.hasNext();) {
@@ -94,7 +90,7 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap
oldValues.put(key, oldValue);
}
- Set changedKeys = new HashSet(diff.getChangedKeys());
+ Set changedKeys = new IdentitySet(diff.getChangedKeys());
for (Iterator it = changedKeys.iterator(); it.hasNext();) {
Object key = it.next();
@@ -144,29 +140,25 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap
}
protected void firstListenerAdded() {
- knownMasterValues = new WritableSet(getRealm());
- cachedValues = new HashMap();
+ knownMasterValues = new IdentityObservableSet(getRealm(), null);
+ cachedValues = new IdentityMap();
knownMasterValues.addSetChangeListener(new ISetChangeListener() {
public void handleSetChange(SetChangeEvent event) {
for (Iterator it = event.diff.getRemovals().iterator(); it
.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- Object key = wrapper.unwrap();
+ Object key = it.next();
detailProperty.removeListener(key, detailListener);
- cachedValues.remove(wrapper);
+ cachedValues.remove(key);
}
for (Iterator it = event.diff.getAdditions().iterator(); it
.hasNext();) {
- IdentityWrapper wrapper = (IdentityWrapper) it.next();
- Object key = wrapper.unwrap();
- cachedValues.put(wrapper, detailProperty.getValue(key));
+ Object key = it.next();
+ cachedValues.put(key, detailProperty.getValue(key));
detailProperty.addListener(key, detailListener);
}
}
});
- for (Iterator it = masterMap.values().iterator(); it.hasNext();) {
- knownMasterValues.add(new IdentityWrapper(it.next()));
- }
+ knownMasterValues.addAll(masterMap.values());
masterMap.addMapChangeListener(masterListener);
masterMap.addStaleListener(staleListener);
@@ -293,12 +285,11 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap
if (cachedValues != null) {
final Set keys = keysFor(masterValue);
- final Object oldValue = cachedValues.get(new IdentityWrapper(
- masterValue));
+ final Object oldValue = cachedValues.get(masterValue);
final Object newValue = detailProperty.getValue(masterValue);
if (!Util.equals(oldValue, newValue)) {
- cachedValues.put(new IdentityWrapper(masterValue), newValue);
+ cachedValues.put(masterValue, newValue);
fireMapChange(new MapDiff() {
public Set getAddedKeys() {
return Collections.EMPTY_SET;
@@ -325,7 +316,7 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap
}
private Set keysFor(Object value) {
- Set keys = new HashSet();
+ Set keys = new IdentitySet();
for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Entry) it.next();
diff --git a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java
index cd20d51b..37d331cb 100644
--- a/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java
+++ b/bundles/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java
@@ -7,11 +7,11 @@
*
* Contributors:
* Matthew Hall - initial API and implementation (bug 194734)
+ * Matthew Hall - bug 262269
******************************************************************************/
package org.eclipse.core.internal.databinding.property.value;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -24,7 +24,7 @@ import org.eclipse.core.databinding.property.IPropertyObservable;
import org.eclipse.core.databinding.property.ISimplePropertyListener;
import org.eclipse.core.databinding.property.SimplePropertyEvent;
import org.eclipse.core.databinding.property.value.SimpleValueProperty;
-import org.eclipse.core.internal.databinding.IdentityWrapper;
+import org.eclipse.core.internal.databinding.IdentityMap;
import org.eclipse.core.internal.databinding.Util;
/**
@@ -51,7 +51,7 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap
}
protected void firstListenerAdded() {
- cachedValues = new HashMap();
+ cachedValues = new IdentityMap();
if (listener == null) {
listener = detailProperty
.adaptListener(new ISimplePropertyListener() {
@@ -78,8 +78,7 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap
protected void hookListener(Object addedKey) {
if (cachedValues != null) {
- cachedValues.put(new IdentityWrapper(addedKey), detailProperty
- .getValue(addedKey));
+ cachedValues.put(addedKey, detailProperty.getValue(addedKey));
detailProperty.addListener(addedKey, listener);
}
}
@@ -87,7 +86,7 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap
protected void unhookListener(Object removedKey) {
if (cachedValues != null) {
detailProperty.removeListener(removedKey, listener);
- cachedValues.remove(new IdentityWrapper(removedKey));
+ cachedValues.remove(removedKey);
}
}
@@ -112,10 +111,10 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap
private void notifyIfChanged(Object key) {
if (cachedValues != null) {
- Object oldValue = cachedValues.get(new IdentityWrapper(key));
+ Object oldValue = cachedValues.get(key);
Object newValue = detailProperty.getValue(key);
if (!Util.equals(oldValue, newValue)) {
- cachedValues.put(new IdentityWrapper(key), newValue);
+ cachedValues.put(key, newValue);
fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
newValue));
}

Back to the top