diff options
author | Nigel Westbury | 2013-03-07 15:17:04 +0000 |
---|---|---|
committer | Nigel Westbury | 2013-03-07 15:29:02 +0000 |
commit | 08f91f39a75191105794c9c8f6a69d0652a9e780 (patch) | |
tree | deee83d6fd2d96099f059a5ff54d6929751e5e04 | |
parent | 28745687d5079793b97b7ce004b27a403ec1c539 (diff) | |
download | org.eclipse.e4.databinding-08f91f39a75191105794c9c8f6a69d0652a9e780.tar.gz org.eclipse.e4.databinding-08f91f39a75191105794c9c8f6a69d0652a9e780.tar.xz org.eclipse.e4.databinding-08f91f39a75191105794c9c8f6a69d0652a9e780.zip |
Bug 335792 - The generics type parameters need to be specified in data binding classesI20130312-1145
145 files changed, 4560 insertions, 3356 deletions
diff --git a/bundles/org.eclipse.core.databinding.observable/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.core.databinding.observable/.settings/org.eclipse.jdt.core.prefs index 9e52c974..b0aff68d 100644 --- a/bundles/org.eclipse.core.databinding.observable/.settings/org.eclipse.jdt.core.prefs +++ b/bundles/org.eclipse.core.databinding.observable/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,3 @@ -#Thu Feb 05 11:35:38 MST 2009 eclipse.preferences.version=1 org.eclipse.jdt.core.builder.cleanOutputFolder=clean org.eclipse.jdt.core.builder.duplicateResourceTask=warning @@ -17,9 +16,9 @@ org.eclipse.jdt.core.codeComplete.localSuffixes= org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -96,7 +95,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enab org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 diff --git a/bundles/org.eclipse.core.databinding.observable/META-INF/MANIFEST.MF b/bundles/org.eclipse.core.databinding.observable/META-INF/MANIFEST.MF index 12b7a1e8..e104cefa 100644 --- a/bundles/org.eclipse.core.databinding.observable/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.core.databinding.observable/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.core.databinding.observable -Bundle-Version: 1.4.1.qualifier +Bundle-Version: 1.5.0.qualifier Bundle-ClassPath: . Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractChangeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractChangeEvent.java new file mode 100644 index 00000000..dac2b3a9 --- /dev/null +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractChangeEvent.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2006, 2007 IBM Corporation 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 + *******************************************************************************/ + +package org.eclipse.core.databinding.observable; + +/** + * Generic change event denoting that the state of an {@link IObservable} object + * has changed. This event does not carry information about the kind of change + * that occurred. + * + * @param <EV> + * + * @since 1.5 + * + */ +public abstract class AbstractChangeEvent<EV extends AbstractChangeEvent<EV>> + extends ObservableEvent<EV> { + + /** + * + */ + private static final long serialVersionUID = -3289969713357065239L; + + static final Object TYPE = new Object(); + + /** + * Creates a new change event object. + * + * @param source + * the observable that changed state + */ + public AbstractChangeEvent(IObservable source) { + super(source); + } + + protected Object getListenerType() { + return TYPE; + } +} diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractObservable.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractObservable.java index 7770eff8..6c7d05d7 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractObservable.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/AbstractObservable.java @@ -19,7 +19,8 @@ import org.eclipse.core.runtime.AssertionFailedException; /** * @since 1.0 */ -public abstract class AbstractObservable extends ChangeManager implements IObservable { +public abstract class AbstractObservable extends ChangeManager implements + IObservable { private boolean disposed = false; /** @@ -31,11 +32,11 @@ public abstract class AbstractObservable extends ChangeManager implements IObser } public synchronized void addChangeListener(IChangeListener listener) { - addListener(ChangeEvent.TYPE, listener); + addListener(AbstractChangeEvent.TYPE, listener); } public synchronized void removeChangeListener(IChangeListener listener) { - removeListener(ChangeEvent.TYPE, listener); + removeListener(AbstractChangeEvent.TYPE, listener); } public synchronized void addStaleListener(IStaleListener listener) { @@ -92,7 +93,8 @@ public abstract class AbstractObservable extends ChangeManager implements IObser * Asserts that the realm is the current realm. * * @see Realm#isCurrent() - * @throws AssertionFailedException if the realm is not the current realm + * @throws AssertionFailedException + * if the realm is not the current realm */ protected void checkRealm() { Assert.isTrue(getRealm().isCurrent(), diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeEvent.java index 60950cf2..7e8c9104 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeEvent.java @@ -19,13 +19,12 @@ package org.eclipse.core.databinding.observable; * @since 1.0 * */ -public class ChangeEvent extends ObservableEvent { +public class ChangeEvent extends AbstractChangeEvent<ChangeEvent> { /** * */ private static final long serialVersionUID = -3241193109844979384L; - static final Object TYPE = new Object(); /** * Creates a new change event object. @@ -44,5 +43,4 @@ public class ChangeEvent extends ObservableEvent { protected Object getListenerType() { return TYPE; } - } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeManager.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeManager.java index d4b2a0d0..fe1e2380 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeManager.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeManager.java @@ -55,10 +55,8 @@ import org.eclipse.core.runtime.ListenerList; length = listenerTypes.length; System.arraycopy(listenerTypes, 0, listenerTypes = new Object[length + 1], 0, length); - System - .arraycopy(listenerLists, 0, - listenerLists = new ListenerList[length + 1], - 0, length); + System.arraycopy(listenerLists, 0, + listenerLists = new ListenerList[length + 1], 0, length); } listenerTypes[length] = listenerType; listenerLists[length] = new ListenerList(); @@ -109,7 +107,17 @@ import org.eclipse.core.runtime.ListenerList; return -1; } - protected void fireEvent(ObservableEvent event) { + protected void fireEvent(ObservableEvent<?> event) { + /* + * Note: We have a type safety warning here because the compiler cannot + * be sure that we are passing an event only to listeners that can + * accept that event. We could do this in a type-safe manner by + * separating listeners into different lists and keeping a map of + * listenerType to listeners. However that would increase memory usage + * and may not be worthwhile. We would also not be able to use the + * ListenerList class because that is not parameterized. + */ + Object listenerType = event.getListenerType(); int listenerTypeIndex = findListenerTypeIndex(listenerType); if (listenerTypeIndex != -1) { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeSupport.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeSupport.java index 902ea8b7..c1e6e64e 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeSupport.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ChangeSupport.java @@ -14,36 +14,35 @@ package org.eclipse.core.databinding.observable; /** * @since 1.0 - * + * */ public abstract class ChangeSupport extends ChangeManager { /** - * @param realm + * @param realm */ public ChangeSupport(Realm realm) { super(realm); } - - public void addListener(Object listenerType, - IObservablesListener listener) { + + public void addListener(Object listenerType, IObservablesListener listener) { super.addListener(listenerType, listener); } - + public void removeListener(Object listenerType, IObservablesListener listener) { super.removeListener(listenerType, listener); } - - public void fireEvent(ObservableEvent event) { + + public void fireEvent(ObservableEvent<?> event) { super.fireEvent(event); } - + /** * */ protected abstract void firstListenerAdded(); - + /** * */ @@ -53,14 +52,14 @@ public abstract class ChangeSupport extends ChangeManager { * @param listener */ public void addChangeListener(IChangeListener listener) { - addListener(ChangeEvent.TYPE, listener); + addListener(AbstractChangeEvent.TYPE, listener); } - + /** * @param listener */ public void removeChangeListener(IChangeListener listener) { - removeListener(ChangeEvent.TYPE, listener); + removeListener(AbstractChangeEvent.TYPE, listener); } /** @@ -69,7 +68,7 @@ public abstract class ChangeSupport extends ChangeManager { public void addStaleListener(IStaleListener listener) { addListener(StaleEvent.TYPE, listener); } - + /** * @param listener */ @@ -78,7 +77,7 @@ public abstract class ChangeSupport extends ChangeManager { } /** - * @param listener + * @param listener * @since 1.2 */ public void addDisposeListener(IDisposeListener listener) { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservable.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservable.java index d079c99b..ea661e6c 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservable.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservable.java @@ -45,7 +45,7 @@ public class DecoratingObservable extends AbstractObservable implements this.decorated = decorated; this.disposedDecoratedOnDispose = disposeDecoratedOnDispose; decorated.addDisposeListener(new IDisposeListener() { - public void handleDispose(DisposeEvent staleEvent) { + public void handleDispose(DisposeEvent disposeEvent) { dispose(); } }); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservableCollection.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservableCollection.java index de13bd05..4ba91992 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservableCollection.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DecoratingObservableCollection.java @@ -17,28 +17,30 @@ import java.util.Iterator; /** * An observable collection which decorates another observable collection * + * @param <E> + * * @since 1.2 */ -public class DecoratingObservableCollection extends DecoratingObservable - implements IObservableCollection { - private IObservableCollection decorated; +public class DecoratingObservableCollection<E> extends DecoratingObservable + implements IObservableCollection<E> { + private IObservableCollection<E> decorated; /** * @param decorated * @param disposeDecoratedOnDispose */ - public DecoratingObservableCollection(IObservableCollection decorated, + public DecoratingObservableCollection(IObservableCollection<E> decorated, boolean disposeDecoratedOnDispose) { super(decorated, disposeDecoratedOnDispose); this.decorated = decorated; } - public boolean add(Object o) { + public boolean add(E o) { getterCalled(); return decorated.add(o); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { getterCalled(); return decorated.addAll(c); } @@ -53,7 +55,7 @@ public class DecoratingObservableCollection extends DecoratingObservable return decorated.contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return decorated.containsAll(c); } @@ -63,10 +65,10 @@ public class DecoratingObservableCollection extends DecoratingObservable return decorated.isEmpty(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - final Iterator decoratedIterator = decorated.iterator(); - return new Iterator() { + final Iterator<E> decoratedIterator = decorated.iterator(); + return new Iterator<E>() { public void remove() { decoratedIterator.remove(); } @@ -76,7 +78,7 @@ public class DecoratingObservableCollection extends DecoratingObservable return decoratedIterator.hasNext(); } - public Object next() { + public E next() { getterCalled(); return decoratedIterator.next(); } @@ -88,12 +90,12 @@ public class DecoratingObservableCollection extends DecoratingObservable return decorated.remove(o); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { getterCalled(); return decorated.removeAll(c); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { getterCalled(); return decorated.retainAll(c); } @@ -108,7 +110,7 @@ public class DecoratingObservableCollection extends DecoratingObservable return decorated.toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); return decorated.toArray(a); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Diffs.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Diffs.java index 5f8792a8..77ed5e24 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Diffs.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Diffs.java @@ -13,14 +13,15 @@ package org.eclipse.core.databinding.observable; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Map.Entry; +import java.util.Set; import org.eclipse.core.databinding.observable.list.ListDiff; import org.eclipse.core.databinding.observable.list.ListDiffEntry; @@ -39,17 +40,19 @@ public class Diffs { * Returns a {@link ListDiff} describing the change between the specified * old and new list states. * + * @param <E> + * * @param oldList * the old list state * @param newList * the new list state * @return the differences between oldList and newList */ - public static ListDiff computeListDiff(List oldList, List newList) { - List diffEntries = new ArrayList(); - createListDiffs(new ArrayList(oldList), newList, diffEntries); - ListDiff listDiff = createListDiff((ListDiffEntry[]) diffEntries - .toArray(new ListDiffEntry[diffEntries.size()])); + public static <E> ListDiff<E> computeListDiff(List<E> oldList, + List<E> newList) { + List<ListDiffEntry<E>> diffEntries = new ArrayList<ListDiffEntry<E>>(); + createListDiffs(new ArrayList<E>(oldList), newList, diffEntries); + ListDiff<E> listDiff = createListDiff(diffEntries); return listDiff; } @@ -57,6 +60,8 @@ public class Diffs { * Returns a lazily computed {@link ListDiff} describing the change between * the specified old and new list states. * + * @param <E> + * * @param oldList * the old list state * @param newList @@ -65,28 +70,36 @@ public class Diffs { * the specified old and new list states. * @since 1.3 */ - public static ListDiff computeLazyListDiff(final List oldList, - final List newList) { - return new ListDiff() { - ListDiff lazyDiff; + public static <E> ListDiff<E> computeLazyListDiff(final List<E> oldList, + final List<E> newList) { + return new ListDiff<E>() { + ListDiff<E> lazyDiff; - public ListDiffEntry[] getDifferences() { + public ListDiffEntry<?>[] getDifferences() { if (lazyDiff == null) { lazyDiff = Diffs.computeListDiff(oldList, newList); } return lazyDiff.getDifferences(); } + + @Override + public List<ListDiffEntry<E>> getDifferencesAsList() { + if (lazyDiff == null) { + lazyDiff = Diffs.computeListDiff(oldList, newList); + } + return lazyDiff.getDifferencesAsList(); + } }; } /** * adapted from EMF's ListDifferenceAnalyzer */ - private static void createListDiffs(List oldList, List newList, - List listDiffs) { + private static <E> void createListDiffs(List<E> oldList, List<E> newList, + List<ListDiffEntry<E>> listDiffs) { int index = 0; - for (Iterator it = newList.iterator(); it.hasNext();) { - Object newValue = it.next(); + for (Iterator<E> it = newList.iterator(); it.hasNext();) { + E newValue = it.next(); if (oldList.size() <= index) { // append newValue to newList listDiffs.add(createListDiffEntry(index, true, newValue)); @@ -94,7 +107,7 @@ public class Diffs { boolean done; do { done = true; - Object oldValue = oldList.get(index); + E oldValue = oldList.get(index); if (oldValue == null ? newValue != null : !oldValue .equals(newValue)) { int oldIndexOfNewValue = listIndexOf(oldList, newValue, @@ -161,7 +174,7 @@ public class Diffs { * @param index * @return the index, or -1 if not found */ - private static int listIndexOf(List list, Object object, int index) { + private static <E> int listIndexOf(List<E> list, Object object, int index) { int size = list.size(); for (int i = index; i < size; i++) { Object candidate = list.get(i); @@ -192,6 +205,8 @@ public class Diffs { * Returns a {@link SetDiff} describing the change between the specified old * and new set states. * + * @param <E> + * * @param oldSet * the old set state * @param newSet @@ -199,10 +214,10 @@ public class Diffs { * @return a {@link SetDiff} describing the change between the specified old * and new set states. */ - public static SetDiff computeSetDiff(Set oldSet, Set newSet) { - Set additions = new HashSet(newSet); + public static <E> SetDiff<E> computeSetDiff(Set<E> oldSet, Set<E> newSet) { + Set<E> additions = new HashSet<E>(newSet); additions.removeAll(oldSet); - Set removals = new HashSet(oldSet); + Set<E> removals = new HashSet<E>(oldSet); removals.removeAll(newSet); return createSetDiff(additions, removals); } @@ -211,6 +226,8 @@ public class Diffs { * Returns a lazily computed {@link SetDiff} describing the change between * the specified old and new set states. * + * @param <E> + * * @param oldSet * the old set state * @param newSet @@ -219,23 +236,24 @@ public class Diffs { * the specified old and new set states. * @since 1.3 */ - public static SetDiff computeLazySetDiff(final Set oldSet, final Set newSet) { - return new SetDiff() { + public static <E> SetDiff<E> computeLazySetDiff(final Set<E> oldSet, + final Set<E> newSet) { + return new SetDiff<E>() { - private SetDiff lazyDiff; + private SetDiff<E> lazyDiff; - private SetDiff getLazyDiff() { + private SetDiff<E> getLazyDiff() { if (lazyDiff == null) { lazyDiff = computeSetDiff(oldSet, newSet); } return lazyDiff; } - public Set getAdditions() { + public Set<E> getAdditions() { return getLazyDiff().getAdditions(); } - public Set getRemovals() { + public Set<E> getRemovals() { return getLazyDiff().getRemovals(); } @@ -246,6 +264,10 @@ public class Diffs { * Returns a {@link MapDiff} describing the change between the specified old * and new map states. * + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param oldMap * the old map state * @param newMap @@ -253,21 +275,23 @@ public class Diffs { * @return a {@link MapDiff} describing the change between the specified old * and new map states. */ - public static MapDiff computeMapDiff(Map oldMap, Map newMap) { + public static <K, V> MapDiff<K, V> computeMapDiff(Map<K, V> oldMap, + Map<K, V> newMap) { // starts out with all keys from the new map, we will remove keys from // the old map as we go - final Set addedKeys = new HashSet(newMap.keySet()); - final Set removedKeys = new HashSet(); - final Set changedKeys = new HashSet(); - final Map oldValues = new HashMap(); - final Map newValues = new HashMap(); - for (Iterator it = oldMap.entrySet().iterator(); it.hasNext();) { - Map.Entry oldEntry = (Entry) it.next(); - Object oldKey = oldEntry.getKey(); + final Set<K> addedKeys = new HashSet<K>(newMap.keySet()); + final Set<K> removedKeys = new HashSet<K>(); + final Set<K> changedKeys = new HashSet<K>(); + final Map<K, V> oldValues = new HashMap<K, V>(); + final Map<K, V> newValues = new HashMap<K, V>(); + for (Iterator<Entry<K, V>> it = oldMap.entrySet().iterator(); it + .hasNext();) { + Map.Entry<K, V> oldEntry = it.next(); + K oldKey = oldEntry.getKey(); if (addedKeys.remove(oldKey)) { // potentially changed key since it is in oldMap and newMap - Object oldValue = oldEntry.getValue(); - Object newValue = newMap.get(oldKey); + V oldValue = oldEntry.getValue(); + V newValue = newMap.get(oldKey); if (!Util.equals(oldValue, newValue)) { changedKeys.add(oldKey); oldValues.put(oldKey, oldValue); @@ -278,28 +302,28 @@ public class Diffs { oldValues.put(oldKey, oldEntry.getValue()); } } - for (Iterator it = addedKeys.iterator(); it.hasNext();) { - Object newKey = it.next(); + for (Iterator<K> it = addedKeys.iterator(); it.hasNext();) { + K newKey = it.next(); newValues.put(newKey, newMap.get(newKey)); } - return new MapDiff() { - public Set getAddedKeys() { + return new MapDiff<K, V>() { + public Set<K> getAddedKeys() { return addedKeys; } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return changedKeys; } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return removedKeys; } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return newValues.get(key); } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValues.get(key); } }; @@ -309,6 +333,10 @@ public class Diffs { * Returns a lazily computed {@link MapDiff} describing the change between * the specified old and new map states. * + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param oldMap * the old map state * @param newMap @@ -317,35 +345,36 @@ public class Diffs { * the specified old and new map states. * @since 1.3 */ - public static MapDiff computeLazyMapDiff(final Map oldMap, final Map newMap) { - return new MapDiff() { + public static <K, V> MapDiff<K, V> computeLazyMapDiff( + final Map<K, V> oldMap, final Map<K, V> newMap) { + return new MapDiff<K, V>() { - private MapDiff lazyDiff; + private MapDiff<K, V> lazyDiff; - private MapDiff getLazyDiff() { + private MapDiff<K, V> getLazyDiff() { if (lazyDiff == null) { lazyDiff = computeMapDiff(oldMap, newMap); } return lazyDiff; } - public Set getAddedKeys() { + public Set<K> getAddedKeys() { return getLazyDiff().getAddedKeys(); } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return getLazyDiff().getRemovedKeys(); } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return getLazyDiff().getChangedKeys(); } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return getLazyDiff().getOldValue(key); } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return getLazyDiff().getNewValue(key); } @@ -353,84 +382,126 @@ public class Diffs { } /** + * @param <T> * @param oldValue * @param newValue * @return a value diff */ - public static ValueDiff createValueDiff(final Object oldValue, - final Object newValue) { - return new ValueDiff() { + public static <T> ValueDiff<T> createValueDiff(final T oldValue, + final T newValue) { + return new ValueDiff<T>() { - public Object getOldValue() { + public T getOldValue() { return oldValue; } - public Object getNewValue() { + public T getNewValue() { return newValue; } }; } /** + * @param <E> * @param additions * @param removals * @return a set diff */ - public static SetDiff createSetDiff(Set additions, Set removals) { - final Set unmodifiableAdditions = Collections + public static <E> SetDiff<E> createSetDiff(Set<E> additions, Set<E> removals) { + final Set<E> unmodifiableAdditions = Collections .unmodifiableSet(additions); - final Set unmodifiableRemovals = Collections.unmodifiableSet(removals); - return new SetDiff() { + final Set<E> unmodifiableRemovals = Collections + .unmodifiableSet(removals); + return new SetDiff<E>() { - public Set getAdditions() { + public Set<E> getAdditions() { return unmodifiableAdditions; } - public Set getRemovals() { + public Set<E> getRemovals() { return unmodifiableRemovals; } }; } /** + * @param <E> * @param difference * @return a list diff with one differing entry */ - public static ListDiff createListDiff(ListDiffEntry difference) { - return createListDiff(new ListDiffEntry[] { difference }); + public static <E> ListDiff<E> createListDiff(ListDiffEntry<E> difference) { + return createListDiff(Collections.singletonList(difference)); } /** + * @param <E> * @param difference1 * @param difference2 * @return a list diff with two differing entries */ - public static ListDiff createListDiff(ListDiffEntry difference1, - ListDiffEntry difference2) { - return createListDiff(new ListDiffEntry[] { difference1, difference2 }); + public static <E> ListDiff<E> createListDiff(ListDiffEntry<E> difference1, + ListDiffEntry<E> difference2) { + List<ListDiffEntry<E>> differences = new ArrayList<ListDiffEntry<E>>(2); + differences.add(difference1); + differences.add(difference2); + return createListDiff(differences); } /** + * This form cannot be used in a type-safe manner because it is not possible + * to construct an array of generic types in a type-safe manner. The form + * below which takes a properly parameterized List is recommended. + * + * @param <E> * @param differences * @return a list diff with the given entries */ - public static ListDiff createListDiff(final ListDiffEntry[] differences) { - return new ListDiff() { - public ListDiffEntry[] getDifferences() { + public static <E> ListDiff<E> createListDiff( + final ListDiffEntry<E>[] differences) { + return new ListDiff<E>() { + public ListDiffEntry<?>[] getDifferences() { + return differences; + } + + @Override + public List<ListDiffEntry<E>> getDifferencesAsList() { + return Arrays.asList(differences); + } + }; + } + + /** + * @param <E> + * @param differences + * @return a list diff with the given entries + * @since 1.5 + */ + public static <E> ListDiff<E> createListDiff( + final List<ListDiffEntry<E>> differences) { + final ListDiffEntry<?>[] differencesArray = differences + .toArray(new ListDiffEntry[differences.size()]); + return new ListDiff<E>() { + public ListDiffEntry<?>[] getDifferences() { + return differencesArray; + } + + @Override + public List<ListDiffEntry<E>> getDifferencesAsList() { return differences; } }; } /** + * @param <E> * @param position * @param isAddition * @param element * @return a list diff entry */ - public static ListDiffEntry createListDiffEntry(final int position, - final boolean isAddition, final Object element) { - return new ListDiffEntry() { + public static <E> ListDiffEntry<E> createListDiffEntry(final int position, + final boolean isAddition, final E element) { + return new ListDiffEntry<E>() { public int getPosition() { return position; @@ -440,136 +511,157 @@ public class Diffs { return isAddition; } - public Object getElement() { + public E getElement() { return element; } }; } /** + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param addedKey * @param newValue * @return a map diff */ - public static MapDiff createMapDiffSingleAdd(final Object addedKey, - final Object newValue) { - return new MapDiff() { + public static <K, V> MapDiff<K, V> createMapDiffSingleAdd(final K addedKey, + final V newValue) { + return new MapDiff<K, V>() { - public Set getAddedKeys() { + public Set<K> getAddedKeys() { return Collections.singleton(addedKey); } - public Set getChangedKeys() { - return Collections.EMPTY_SET; + public Set<K> getChangedKeys() { + return Collections.emptySet(); } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return newValue; } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return null; } - public Set getRemovedKeys() { - return Collections.EMPTY_SET; + public Set<K> getRemovedKeys() { + return Collections.emptySet(); } }; } /** + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param existingKey * @param oldValue * @param newValue * @return a map diff */ - public static MapDiff createMapDiffSingleChange(final Object existingKey, - final Object oldValue, final Object newValue) { - return new MapDiff() { + public static <K, V> MapDiff<K, V> createMapDiffSingleChange( + final K existingKey, final V oldValue, final V newValue) { + return new MapDiff<K, V>() { - public Set getAddedKeys() { - return Collections.EMPTY_SET; + public Set<K> getAddedKeys() { + return Collections.emptySet(); } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return Collections.singleton(existingKey); } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return newValue; } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValue; } - public Set getRemovedKeys() { - return Collections.EMPTY_SET; + public Set<K> getRemovedKeys() { + return Collections.emptySet(); } }; } /** + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param removedKey * @param oldValue * @return a map diff */ - public static MapDiff createMapDiffSingleRemove(final Object removedKey, - final Object oldValue) { - return new MapDiff() { + public static <K, V> MapDiff<K, V> createMapDiffSingleRemove( + final K removedKey, final V oldValue) { + return new MapDiff<K, V>() { - public Set getAddedKeys() { - return Collections.EMPTY_SET; + public Set<K> getAddedKeys() { + return Collections.emptySet(); } - public Set getChangedKeys() { - return Collections.EMPTY_SET; + public Set<K> getChangedKeys() { + return Collections.emptySet(); } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return null; } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValue; } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return Collections.singleton(removedKey); } }; } /** + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param copyOfOldMap * @return a map diff */ - public static MapDiff createMapDiffRemoveAll(final Map copyOfOldMap) { - return new MapDiff() { + public static <K, V> MapDiff<K, V> createMapDiffRemoveAll( + final Map<K, V> copyOfOldMap) { + return new MapDiff<K, V>() { - public Set getAddedKeys() { - return Collections.EMPTY_SET; + public Set<K> getAddedKeys() { + return Collections.emptySet(); } - public Set getChangedKeys() { - return Collections.EMPTY_SET; + public Set<K> getChangedKeys() { + return Collections.emptySet(); } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return null; } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return copyOfOldMap.get(key); } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return copyOfOldMap.keySet(); } }; } /** + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @param addedKeys * @param removedKeys * @param changedKeys @@ -577,28 +669,28 @@ public class Diffs { * @param newValues * @return a map diff */ - public static MapDiff createMapDiff(final Set addedKeys, - final Set removedKeys, final Set changedKeys, final Map oldValues, - final Map newValues) { - return new MapDiff() { + public static <K, V> MapDiff<K, V> createMapDiff(final Set<K> addedKeys, + final Set<K> removedKeys, final Set<K> changedKeys, + final Map<K, V> oldValues, final Map<K, V> newValues) { + return new MapDiff<K, V>() { - public Set getAddedKeys() { + public Set<K> getAddedKeys() { return addedKeys; } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return changedKeys; } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return newValues.get(key); } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValues.get(key); } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return removedKeys; } }; diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DisposeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DisposeEvent.java index f99986e5..fac5c3b9 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DisposeEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/DisposeEvent.java @@ -16,7 +16,7 @@ package org.eclipse.core.databinding.observable; * * @since 1.2 */ -public class DisposeEvent extends ObservableEvent { +public class DisposeEvent extends ObservableEvent<DisposeEvent> { /** * */ diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/IObservableCollection.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/IObservableCollection.java index 8d1ee9b2..2aa0867d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/IObservableCollection.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/IObservableCollection.java @@ -22,6 +22,8 @@ import org.eclipse.core.databinding.observable.set.IObservableSet; * changes have to be added using more concrete subtypes such as * {@link IObservableList} or {@link IObservableSet}. * + * @param <T> + * * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that @@ -31,7 +33,7 @@ import org.eclipse.core.databinding.observable.set.IObservableSet; * * @since 1.0 */ -public interface IObservableCollection extends IObservable, Collection { +public interface IObservableCollection<T> extends IObservable, Collection<T> { /** * Returns the element type of this observable collection, or diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableEvent.java index 38a865c5..20da2fb3 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableEvent.java @@ -18,10 +18,13 @@ import java.util.EventObject; * events fired by observables must be derived from this class so that the way * of dispatching events can be improved in later versions of the framework. * + * @param <EV> + * * @since 1.0 * */ -public abstract class ObservableEvent extends EventObject { +public abstract class ObservableEvent<EV extends ObservableEvent<EV>> extends + EventObject { /** * Creates a new observable event. diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableTracker.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableTracker.java index 0c27e3bf..544c954f 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableTracker.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/ObservableTracker.java @@ -65,15 +65,15 @@ public class ObservableTracker { * changes the current value, it remembers the old value as a local variable * and restores the old value when the method exits. */ - private static ThreadLocal currentChangeListener = new ThreadLocal(); + private static ThreadLocal<IChangeListener> currentChangeListener = new ThreadLocal<IChangeListener>(); - private static ThreadLocal currentStaleListener = new ThreadLocal(); + private static ThreadLocal<IStaleListener> currentStaleListener = new ThreadLocal<IStaleListener>(); - private static ThreadLocal currentGetterCalledSet = new ThreadLocal(); + private static ThreadLocal<Set<IObservable>> currentGetterCalledSet = new ThreadLocal<Set<IObservable>>(); - private static ThreadLocal currentObservableCreatedSet = new ThreadLocal(); + private static ThreadLocal<Set<IObservable>> currentObservableCreatedSet = new ThreadLocal<Set<IObservable>>(); - private static ThreadLocal currentIgnoreCount = new ThreadLocal(); + private static ThreadLocal<Integer> currentIgnoreCount = new ThreadLocal<Integer>(); /** * Invokes the given runnable, and returns the set of IObservables that were @@ -93,14 +93,12 @@ public class ObservableTracker { public static IObservable[] runAndMonitor(Runnable runnable, IChangeListener changeListener, IStaleListener staleListener) { // Remember the previous value in the listener stack - Set lastObservableSet = (Set) currentGetterCalledSet.get(); - IChangeListener lastChangeListener = (IChangeListener) currentChangeListener - .get(); - IStaleListener lastStaleListener = (IStaleListener) currentStaleListener - .get(); - Integer lastIgnore = (Integer) currentIgnoreCount.get(); + Set<IObservable> lastObservableSet = currentGetterCalledSet.get(); + IChangeListener lastChangeListener = currentChangeListener.get(); + IStaleListener lastStaleListener = currentStaleListener.get(); + Integer lastIgnore = currentIgnoreCount.get(); - Set observableSet = new IdentitySet(); + Set<IObservable> observableSet = new IdentitySet<IObservable>(); // Push the new listeners to the top of the stack currentGetterCalledSet.set(observableSet); currentChangeListener.set(changeListener); @@ -118,8 +116,7 @@ public class ObservableTracker { currentIgnoreCount.set(lastIgnore); } - return (IObservable[]) observableSet - .toArray(new IObservable[observableSet.size()]); + return observableSet.toArray(new IObservable[observableSet.size()]); } /** @@ -139,10 +136,11 @@ public class ObservableTracker { * @since 1.2 */ public static IObservable[] runAndCollect(Runnable runnable) { - Set lastObservableCreatedSet = (Set) currentObservableCreatedSet.get(); - Integer lastIgnore = (Integer) currentIgnoreCount.get(); + Set<IObservable> lastObservableCreatedSet = currentObservableCreatedSet + .get(); + Integer lastIgnore = currentIgnoreCount.get(); - Set observableSet = new IdentitySet(); + Set<IObservable> observableSet = new IdentitySet<IObservable>(); // Push the new listeners to the top of the stack currentObservableCreatedSet.set(observableSet); currentIgnoreCount.set(null); @@ -156,22 +154,19 @@ public class ObservableTracker { currentIgnoreCount.set(lastIgnore); } - return (IObservable[]) observableSet - .toArray(new IObservable[observableSet.size()]); + return observableSet.toArray(new IObservable[observableSet.size()]); } private static void checkUnmatchedIgnore(Runnable runnable) { if (isIgnore()) { - Policy - .getLog() - .log( - new Status( - IStatus.ERROR, - Policy.JFACE_DATABINDING, - "There were " //$NON-NLS-1$ - + currentIgnoreCount.get() - + " unmatched setIgnore(true) invocations in runnable " //$NON-NLS-1$ - + runnable)); + Policy.getLog() + .log(new Status( + IStatus.ERROR, + Policy.JFACE_DATABINDING, + "There were " //$NON-NLS-1$ + + currentIgnoreCount.get() + + " unmatched setIgnore(true) invocations in runnable " //$NON-NLS-1$ + + runnable)); } } @@ -196,7 +191,7 @@ public class ObservableTracker { * @since 1.3 */ public static void setIgnore(boolean ignore) { - Integer lastCount = (Integer) currentIgnoreCount.get(); + Integer lastCount = currentIgnoreCount.get(); int newCount = (lastCount == null ? 0 : lastCount.intValue()) + (ignore ? 1 : -1); @@ -259,15 +254,13 @@ public class ObservableTracker { if (isIgnore()) return; - Set getterCalledSet = (Set) currentGetterCalledSet.get(); + Set<IObservable> getterCalledSet = currentGetterCalledSet.get(); if (getterCalledSet != null && getterCalledSet.add(observable)) { // If anyone is listening for observable usage... - IChangeListener changeListener = (IChangeListener) currentChangeListener - .get(); + IChangeListener changeListener = currentChangeListener.get(); if (changeListener != null) observable.addChangeListener(changeListener); - IStaleListener staleListener = (IStaleListener) currentStaleListener - .get(); + IStaleListener staleListener = currentStaleListener.get(); if (staleListener != null) observable.addStaleListener(staleListener); } @@ -283,7 +276,8 @@ public class ObservableTracker { public static void observableCreated(IObservable observable) { if (isIgnore()) return; - Set observableCreatedSet = (Set) currentObservableCreatedSet.get(); + Set<IObservable> observableCreatedSet = currentObservableCreatedSet + .get(); if (observableCreatedSet != null) { observableCreatedSet.add(observable); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Observables.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Observables.java index 1c08fc17..66d49e46 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Observables.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Observables.java @@ -84,6 +84,8 @@ public class Observables { * from a wrapped {@link IVetoableValue}. * </ul> * + * @param <T> + * * @param delay * the delay in milliseconds * @param observable @@ -94,30 +96,34 @@ public class Observables { * * @since 1.2 */ - public static IObservableValue observeDelayedValue(int delay, - IObservableValue observable) { - return new DelayedObservableValue(delay, observable); + public static <T> IObservableValue<T> observeDelayedValue(int delay, + IObservableValue<T> observable) { + return new DelayedObservableValue<T>(delay, observable); } /** * Returns an unmodifiable observable value backed by the given observable * value. * + * @param <T> + * * @param value * the value to wrap in an unmodifiable value * @return an unmodifiable observable value backed by the given observable * value * @since 1.1 */ - public static IObservableValue unmodifiableObservableValue( - IObservableValue value) { + public static <T> IObservableValue<T> unmodifiableObservableValue( + IObservableValue<T> value) { Assert.isNotNull(value, "Argument 'value' cannot be null"); //$NON-NLS-1$ - return new UnmodifiableObservableValue(value); + return new UnmodifiableObservableValue<T>(value); } /** * Returns an observable value with the given constant value. * + * @param <T> + * * @param realm * the observable's realm * @param value @@ -127,14 +133,16 @@ public class Observables { * @return an immutable observable value with the given constant value * @since 1.1 */ - public static IObservableValue constantObservableValue(Realm realm, - Object value, Object valueType) { - return new ConstantObservableValue(realm, value, valueType); + public static <T> IObservableValue<T> constantObservableValue(Realm realm, + T value, Object valueType) { + return new ConstantObservableValue<T>(realm, value, valueType); } /** * Returns an observable value with the given constant value. * + * @param <T> + * * @param realm * the observable's realm * @param value @@ -142,14 +150,16 @@ public class Observables { * @return an immutable observable value with the given constant value * @since 1.1 */ - public static IObservableValue constantObservableValue(Realm realm, - Object value) { + public static <T> IObservableValue<T> constantObservableValue(Realm realm, + T value) { return constantObservableValue(realm, value, null); } /** * Returns an observable value with the given constant value. * + * @param <T> + * * @param value * the observable's constant value * @param valueType @@ -157,20 +167,22 @@ public class Observables { * @return an immutable observable value with the given constant value * @since 1.1 */ - public static IObservableValue constantObservableValue(Object value, - Object valueType) { + public static <T> IObservableValue<T> constantObservableValue(T value, + T valueType) { return constantObservableValue(Realm.getDefault(), value, valueType); } /** * Returns an observable value with the given constant value. * + * @param <T> + * * @param value * the observable's constant value * @return an immutable observable value with the given constant value * @since 1.1 */ - public static IObservableValue constantObservableValue(Object value) { + public static <T> IObservableValue<T> constantObservableValue(T value) { return constantObservableValue(Realm.getDefault(), value, null); } @@ -178,53 +190,62 @@ public class Observables { * Returns an unmodifiable observable list backed by the given observable * list. * + * @param <E> + * * @param list * the list to wrap in an unmodifiable list * @return an unmodifiable observable list backed by the given observable * list */ - public static IObservableList unmodifiableObservableList( - IObservableList list) { + public static <E> IObservableList<E> unmodifiableObservableList( + IObservableList<E> list) { if (list == null) { throw new IllegalArgumentException("List parameter cannot be null."); //$NON-NLS-1$ } - return new UnmodifiableObservableList(list); + return new UnmodifiableObservableList<E>(list); } /** * Returns an unmodifiable observable set backed by the given observable * set. * + * @param <E> + * * @param set * the set to wrap in an unmodifiable set * @return an unmodifiable observable set backed by the given observable set * @since 1.1 */ - public static IObservableSet unmodifiableObservableSet(IObservableSet set) { + public static <E> IObservableSet<E> unmodifiableObservableSet( + IObservableSet<E> set) { if (set == null) { throw new IllegalArgumentException("Set parameter cannot be null"); //$NON-NLS-1$ } - return new UnmodifiableObservableSet(set); + return new UnmodifiableObservableSet<E>(set); } /** * Returns an unmodifiable observable map backed by the given observable * map. * + * @param <K> + * @param <V> + * * @param map * the map to wrap in an unmodifiable map * @return an unmodifiable observable map backed by the given observable * map. * @since 1.2 */ - public static IObservableMap unmodifiableObservableMap(IObservableMap map) { + public static <K, V> IObservableMap<K, V> unmodifiableObservableMap( + IObservableMap<K, V> map) { if (map == null) { throw new IllegalArgumentException("Map parameter cannot be null"); //$NON-NLS-1$ } - return new UnmodifiableObservableMap(map); + return new UnmodifiableObservableMap<K, V>(map); } /** @@ -233,7 +254,7 @@ public class Observables { * * @return an empty observable list. */ - public static IObservableList emptyObservableList() { + public static IObservableList<Object> emptyObservableList() { return emptyObservableList(Realm.getDefault(), null); } @@ -247,7 +268,7 @@ public class Observables { * @return an empty observable list * @since 1.1 */ - public static IObservableList emptyObservableList(Object elementType) { + public static IObservableList<Object> emptyObservableList(Object elementType) { return emptyObservableList(Realm.getDefault(), elementType); } @@ -260,7 +281,7 @@ public class Observables { * the realm of the returned list * @return an empty observable list. */ - public static IObservableList emptyObservableList(Realm realm) { + public static IObservableList<Object> emptyObservableList(Realm realm) { return emptyObservableList(realm, null); } @@ -276,9 +297,9 @@ public class Observables { * @return an empty observable list * @since 1.1 */ - public static IObservableList emptyObservableList(Realm realm, + public static IObservableList<Object> emptyObservableList(Realm realm, Object elementType) { - return new EmptyObservableList(realm, elementType); + return new EmptyObservableList<Object>(realm, elementType); } /** @@ -287,7 +308,7 @@ public class Observables { * * @return an empty observable set. */ - public static IObservableSet emptyObservableSet() { + public static IObservableSet<Object> emptyObservableSet() { return emptyObservableSet(Realm.getDefault(), null); } @@ -301,7 +322,7 @@ public class Observables { * @return an empty observable set * @since 1.1 */ - public static IObservableSet emptyObservableSet(Object elementType) { + public static IObservableSet<Object> emptyObservableSet(Object elementType) { return emptyObservableSet(Realm.getDefault(), elementType); } @@ -314,7 +335,7 @@ public class Observables { * the realm of the returned set * @return an empty observable set. */ - public static IObservableSet emptyObservableSet(Realm realm) { + public static IObservableSet<Object> emptyObservableSet(Realm realm) { return emptyObservableSet(realm, null); } @@ -330,19 +351,21 @@ public class Observables { * @return an empty observable set * @since 1.1 */ - public static IObservableSet emptyObservableSet(Realm realm, + public static IObservableSet<Object> emptyObservableSet(Realm realm, Object elementType) { - return new EmptyObservableSet(realm, elementType); + return new EmptyObservableSet<Object>(realm, elementType); } /** * Returns an observable set backed by the given set. * + * @param <E> + * * @param set * the set to wrap in an IObservableSet * @return an observable set backed by the given set */ - public static IObservableSet staticObservableSet(Set set) { + public static <E> IObservableSet<E> staticObservableSet(Set<E> set) { return staticObservableSet(Realm.getDefault(), set, Object.class); } @@ -350,6 +373,8 @@ public class Observables { * Returns an observable set of the given element type, backed by the given * set. * + * @param <E> + * * @param set * the set to wrap in an IObservableSet * @param elementType @@ -357,7 +382,8 @@ public class Observables { * @return Returns an observable set backed by the given unchanging set * @since 1.1 */ - public static IObservableSet staticObservableSet(Set set, Object elementType) { + public static <E> IObservableSet<E> staticObservableSet(Set<E> set, + Object elementType) { return staticObservableSet(Realm.getDefault(), set, elementType); } @@ -365,13 +391,16 @@ public class Observables { * Returns an observable set belonging to the given realm, backed by the * given set. * + * @param <E> + * * @param realm * the realm of the returned set * @param set * the set to wrap in an IObservableSet * @return an observable set backed by the given unchanging set */ - public static IObservableSet staticObservableSet(Realm realm, Set set) { + public static <E> IObservableSet<E> staticObservableSet(Realm realm, + Set<E> set) { return staticObservableSet(realm, set, Object.class); } @@ -379,6 +408,8 @@ public class Observables { * Returns an observable set of the given element type and belonging to the * given realm, backed by the given set. * + * @param <E> + * * @param realm * the realm of the returned set * @param set @@ -388,9 +419,9 @@ public class Observables { * @return an observable set backed by the given set * @since 1.1 */ - public static IObservableSet staticObservableSet(Realm realm, Set set, - Object elementType) { - return new ObservableSet(realm, set, elementType) { + public static <E> IObservableSet<E> staticObservableSet(Realm realm, + Set<E> set, Object elementType) { + return new ObservableSet<E>(realm, set, elementType) { public synchronized void addChangeListener(IChangeListener listener) { } @@ -398,7 +429,7 @@ public class Observables { } public synchronized void addSetChangeListener( - ISetChangeListener listener) { + ISetChangeListener<? super E> listener) { } }; } @@ -408,13 +439,16 @@ public class Observables { * observable, and fires the same events as the given observable, but can be * disposed of without disposing of the wrapped observable. * + * @param <T> + * * @param target * the observable value to wrap * @return a disposable proxy for the given observable value. * @since 1.2 */ - public static IObservableValue proxyObservableValue(IObservableValue target) { - return new DecoratingObservableValue(target, false); + public static <T> IObservableValue<T> proxyObservableValue( + IObservableValue<T> target) { + return new DecoratingObservableValue<T>(target, false); } /** @@ -422,12 +456,15 @@ public class Observables { * set, and fires the same events as the given set, but can be disposed of * without disposing of the wrapped set. * + * @param <E> + * * @param target * the set to wrap * @return a disposable proxy for the given observable set */ - public static IObservableSet proxyObservableSet(IObservableSet target) { - return new DecoratingObservableSet(target, false); + public static <E> IObservableSet<E> proxyObservableSet( + IObservableSet<E> target) { + return new DecoratingObservableSet<E>(target, false); } /** @@ -435,13 +472,16 @@ public class Observables { * list, and fires the same events as the given list, but can be disposed of * without disposing of the wrapped list. * + * @param <E> + * * @param target * the list to wrap * @return a disposable proxy for the given observable list * @since 1.1 */ - public static IObservableList proxyObservableList(IObservableList target) { - return new DecoratingObservableList(target, false); + public static <E> IObservableList<E> proxyObservableList( + IObservableList<E> target) { + return new DecoratingObservableList<E>(target, false); } /** @@ -449,23 +489,29 @@ public class Observables { * map, and fires the same events as the given map, but can be disposed of * without disposing of the wrapped map. * + * @param <K> + * @param <V> + * * @param target * the map to wrap * @return a disposable proxy for the given observable map * @since 1.2 */ - public static IObservableMap proxyObservableMap(IObservableMap target) { - return new DecoratingObservableMap(target, false); + public static <K, V> IObservableMap<K, V> proxyObservableMap( + IObservableMap<K, V> target) { + return new DecoratingObservableMap<K, V>(target, false); } /** * Returns an observable list backed by the given list. * + * @param <E> + * * @param list * the list to wrap in an IObservableList * @return an observable list backed by the given unchanging list */ - public static IObservableList staticObservableList(List list) { + public static <E> IObservableList<E> staticObservableList(List<E> list) { return staticObservableList(Realm.getDefault(), list, Object.class); } @@ -473,6 +519,8 @@ public class Observables { * Returns an observable list of the given element type, backed by the given * list. * + * @param <E> + * * @param list * the list to wrap in an IObservableList * @param elementType @@ -480,7 +528,7 @@ public class Observables { * @return an observable list backed by the given unchanging list * @since 1.1 */ - public static IObservableList staticObservableList(List list, + public static <E> IObservableList<E> staticObservableList(List<E> list, Object elementType) { return staticObservableList(Realm.getDefault(), list, elementType); } @@ -489,13 +537,16 @@ public class Observables { * Returns an observable list belonging to the given realm, backed by the * given list. * + * @param <E> + * * @param realm * the realm of the returned list * @param list * the list to wrap in an IObservableList * @return an observable list backed by the given unchanging list */ - public static IObservableList staticObservableList(Realm realm, List list) { + public static <E> IObservableList<E> staticObservableList(Realm realm, + List<E> list) { return staticObservableList(realm, list, Object.class); } @@ -503,6 +554,8 @@ public class Observables { * Returns an observable list of the given element type and belonging to the * given realm, backed by the given list. * + * @param <E> + * * @param realm * the realm of the returned list * @param list @@ -512,9 +565,9 @@ public class Observables { * @return an observable list backed by the given unchanging list * @since 1.1 */ - public static IObservableList staticObservableList(Realm realm, List list, - Object elementType) { - return new ObservableList(realm, list, elementType) { + public static <E> IObservableList<E> staticObservableList(Realm realm, + List<E> list, Object elementType) { + return new ObservableList<E>(realm, list, elementType) { public synchronized void addChangeListener(IChangeListener listener) { } @@ -522,7 +575,7 @@ public class Observables { } public synchronized void addListChangeListener( - IListChangeListener listener) { + IListChangeListener<E> listener) { } }; } @@ -538,7 +591,7 @@ public class Observables { * * @since 1.1 */ - public static IObservableValue observeStale(IObservable observable) { + public static IObservableValue<Boolean> observeStale(IObservable observable) { return new StalenessObservableValue(observable); } @@ -551,6 +604,10 @@ public class Observables { * transition between these two states is not considered a value change and * no event is fired. * + * @param <K> + * + * @param <V> + * * @param map * the observable map whose entry will be tracked. * @param key @@ -559,8 +616,8 @@ public class Observables { * specified key in the given map * @since 1.2 */ - public static IObservableValue observeMapEntry(IObservableMap map, - Object key) { + public static <K, V> IObservableValue<V> observeMapEntry( + IObservableMap<K, V> map, K key) { return observeMapEntry(map, key, map.getValueType()); } @@ -573,6 +630,10 @@ public class Observables { * transition between these two states is not considered a value change and * no event is fired. * + * @param <K> + * + * @param <V> + * * @param map * the observable map whose entry will be tracked. * @param key @@ -584,17 +645,20 @@ public class Observables { * specified key in the given map * @since 1.1 */ - public static IObservableValue observeMapEntry(IObservableMap map, - Object key, Object valueType) { + public static <K, V> IObservableValue<V> observeMapEntry( + IObservableMap<K, V> map, K key, Object valueType) { if (valueType == null) valueType = map.getValueType(); - return new MapEntryObservableValue(map, key, valueType); + return new MapEntryObservableValue<K, V>(map, key, valueType); } /** - * Returns a factory for creating obervable values tracking the value of the - * {@link IObservableMap observable map} entry identified by a particular - * key. + * Returns a factory for creating observable values tracking the value of + * the {@link IObservableMap observable map} entry identified by a + * particular key. + * + * @param <K> + * @param <V> * * @param map * the observable map whose entry will be tracked. @@ -605,10 +669,10 @@ public class Observables { * the observable map entry identified by a particular key object. * @since 1.1 */ - public static IObservableFactory mapEntryValueFactory( - final IObservableMap map, final Object valueType) { - return new IObservableFactory() { - public IObservable createObservable(Object key) { + public static <K, V> IObservableFactory<K, IObservableValue<V>> mapEntryValueFactory( + final IObservableMap<K, V> map, final Object valueType) { + return new IObservableFactory<K, IObservableValue<V>>() { + public IObservableValue<V> createObservable(K key) { return observeMapEntry(map, key, valueType); } }; @@ -618,6 +682,9 @@ public class Observables { * Helper method for <code>MasterDetailObservables.detailValue(master, * mapEntryValueFactory(map, valueType), valueType)</code>. * + * @param <K> + * @param <V> + * * @param map * the observable map whose entry will be tracked. * @param master @@ -631,8 +698,9 @@ public class Observables { * observable value * @since 1.1 */ - public static IObservableValue observeDetailMapEntry(IObservableMap map, - IObservableValue master, Object valueType) { + public static <K, V> IObservableValue<V> observeDetailMapEntry( + IObservableMap<K, V> map, IObservableValue<K> master, + Object valueType) { return MasterDetailObservables.detailValue(master, mapEntryValueFactory(map, valueType), valueType); } @@ -644,17 +712,19 @@ public class Observables { * observable is disposed. This method assumes that both observables are on * the same realm. * + * @param <T> + * * @param source * the source observable * @param destination * the destination observable * @since 1.2 */ - public static void pipe(IObservableValue source, - final IObservableValue destination) { + public static <T> void pipe(IObservableValue<T> source, + final IObservableValue<? super T> destination) { destination.setValue(source.getValue()); - source.addValueChangeListener(new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + source.addValueChangeListener(new IValueChangeListener<T>() { + public void handleValueChange(ValueChangeEvent<T> event) { destination.setValue(event.diff.getNewValue()); } }); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Realm.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Realm.java index 9d540f6c..219ff825 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Realm.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Realm.java @@ -79,18 +79,18 @@ import org.eclipse.core.runtime.Status; */ public abstract class Realm { - private static ThreadLocal defaultRealm = new ThreadLocal(); + private static ThreadLocal<Realm> defaultRealm = new ThreadLocal<Realm>(); /** - * Returns the default realm for the calling thread, or <code>null</code> - * if no default realm has been set. + * Returns the default realm for the calling thread, or <code>null</code> if + * no default realm has been set. * * @return the default realm, or <code>null</code> */ public static Realm getDefault() { - return (Realm) defaultRealm.get(); + return defaultRealm.get(); } - + /** * Sets the default realm for the calling thread, returning the current * default thread. This method is inherently unsafe, it is recommended to @@ -115,11 +115,11 @@ public abstract class Realm { abstract public boolean isCurrent(); private Thread workerThread; - + private volatile Timer timer; Queue workQueue = new Queue(); - + /** * Runs the given runnable. If an exception occurs within the runnable, it * is logged and not re-thrown. If the runnable implements @@ -135,15 +135,14 @@ public abstract class Realm { } else { safeRunnable = new ISafeRunnable() { public void handleException(Throwable exception) { - Policy - .getLog() - .log( - new Status( - IStatus.ERROR, - Policy.JFACE_DATABINDING, - IStatus.OK, - "Unhandled exception: " + exception.getMessage(), exception)); //$NON-NLS-1$ + Policy.getLog() + .log(new Status( + IStatus.ERROR, + Policy.JFACE_DATABINDING, + IStatus.OK, + "Unhandled exception: " + exception.getMessage(), exception)); //$NON-NLS-1$ } + public void run() throws Exception { runnable.run(); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/StaleEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/StaleEvent.java index 14e8c76b..c819d92e 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/StaleEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/StaleEvent.java @@ -24,7 +24,7 @@ package org.eclipse.core.databinding.observable; * @since 1.0 * */ -public class StaleEvent extends ObservableEvent { +public class StaleEvent extends ObservableEvent<StaleEvent> { /** * Creates a new stale event. diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/AbstractObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/AbstractObservableList.java index 1bd705d8..be752676 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/AbstractObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/AbstractObservableList.java @@ -39,11 +39,13 @@ import org.eclipse.core.runtime.AssertionFailedException; * listeners may be invoked from any thread. * </p> * + * @param <E> + * * @since 1.0 * */ -public abstract class AbstractObservableList extends AbstractList implements - IObservableList { +public abstract class AbstractObservableList<E> extends AbstractList<E> + implements IObservableList<E> { private final class PrivateChangeSupport extends ChangeSupport { private PrivateChangeSupport(Realm realm) { super(realm); @@ -67,7 +69,7 @@ public abstract class AbstractObservableList extends AbstractList implements private volatile boolean disposed = false; /** - * @param realm + * @param realm * */ public AbstractObservableList(Realm realm) { @@ -83,7 +85,7 @@ public abstract class AbstractObservableList extends AbstractList implements public AbstractObservableList() { this(Realm.getDefault()); } - + /** * Returns whether this observable list has any registered listeners. * @@ -99,22 +101,24 @@ public abstract class AbstractObservableList extends AbstractList implements return false; } - public synchronized void addListChangeListener(IListChangeListener listener) { + public synchronized void addListChangeListener( + IListChangeListener<E> listener) { if (!disposed) { changeSupport.addListener(ListChangeEvent.TYPE, listener); } } - public synchronized void removeListChangeListener(IListChangeListener listener) { + public synchronized void removeListChangeListener( + IListChangeListener<E> listener) { if (!disposed) { changeSupport.removeListener(ListChangeEvent.TYPE, listener); } } - protected void fireListChange(ListDiff diff) { + protected void fireListChange(ListDiff<E> diff) { // fire general change event first fireChange(); - changeSupport.fireEvent(new ListChangeEvent(this, diff)); + changeSupport.fireEvent(new ListChangeEvent<E>(this, diff)); } public synchronized void addChangeListener(IChangeListener listener) { @@ -234,10 +238,10 @@ public abstract class AbstractObservableList extends AbstractList implements return super.contains(o); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - final Iterator wrappedIterator = super.iterator(); - return new Iterator() { + final Iterator<E> wrappedIterator = super.iterator(); + return new Iterator<E>() { public void remove() { wrappedIterator.remove(); } @@ -246,7 +250,7 @@ public abstract class AbstractObservableList extends AbstractList implements return wrappedIterator.hasNext(); } - public Object next() { + public E next() { return wrappedIterator.next(); } }; @@ -257,14 +261,14 @@ public abstract class AbstractObservableList extends AbstractList implements return super.toArray(); } - public Object[] toArray(Object a[]) { + public <T> T[] toArray(T a[]) { getterCalled(); return super.toArray(a); } // Modification Operations - public boolean add(Object o) { + public boolean add(E o) { getterCalled(); return super.add(o); } @@ -287,12 +291,13 @@ public abstract class AbstractObservableList extends AbstractList implements * range <code>0 <= newIndex < size()</code>. * @return the element that was moved. * @throws IndexOutOfBoundsException - * if either argument is out of range (<code>0 <= index < size()</code>). + * if either argument is out of range ( + * <code>0 <= index < size()</code>). * @see ListDiffVisitor#handleMove(int, int, Object) * @see ListDiff#accept(ListDiffVisitor) * @since 1.1 */ - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { checkRealm(); int size = doGetSize(); if (oldIndex < 0 || oldIndex >= size) @@ -301,7 +306,7 @@ public abstract class AbstractObservableList extends AbstractList implements if (newIndex < 0 || newIndex >= size) throw new IndexOutOfBoundsException( "newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ - Object element = remove(oldIndex); + E element = remove(oldIndex); add(newIndex, element); return element; } @@ -313,27 +318,27 @@ public abstract class AbstractObservableList extends AbstractList implements // Bulk Modification Operations - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return super.containsAll(c); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { getterCalled(); return super.addAll(c); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { getterCalled(); return super.addAll(c); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { getterCalled(); return super.removeAll(c); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { getterCalled(); return super.retainAll(c); } @@ -363,7 +368,7 @@ public abstract class AbstractObservableList extends AbstractList implements public Realm getRealm() { return realm; } - + /** * Asserts that the realm is the current realm. * diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ComputedList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ComputedList.java index 6823362c..b327717f 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ComputedList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ComputedList.java @@ -71,10 +71,12 @@ import org.eclipse.core.databinding.observable.value.IObservableValue; * System.out.println(fibonacci); // => "[0, 1, 1, 2, 3]" * </pre> * + * @param <E> + * * @since 1.1 */ -public abstract class ComputedList extends AbstractObservableList { - private List cachedList = new ArrayList(); +public abstract class ComputedList<E> extends AbstractObservableList<E> { + private List<E> cachedList = new ArrayList<E>(); private boolean dirty = true; private boolean stale = false; @@ -149,25 +151,30 @@ public abstract class ComputedList extends AbstractObservableList { * </p> * */ - private class PrivateInterface implements Runnable, IChangeListener, - IStaleListener { - public void run() { - cachedList = calculate(); - if (cachedList == null) - cachedList = Collections.EMPTY_LIST; + private class PrivateChangeInterface implements IChangeListener { + public void handleChange(ChangeEvent event) { + makeDirty(); } + } + private class PrivateStaleInterface implements IStaleListener { public void handleStale(StaleEvent event) { if (!dirty) makeStale(); } + } - public void handleChange(ChangeEvent event) { - makeDirty(); + private class PrivateRunnableInterface implements Runnable { + public void run() { + cachedList = calculate(); + if (cachedList == null) + cachedList = Collections.emptyList(); } } - private PrivateInterface privateInterface = new PrivateInterface(); + private IChangeListener privateChangeInterface = new PrivateChangeInterface(); + private IStaleListener privateStaleInterface = new PrivateStaleInterface(); + private Runnable privateRunnableInterface = new PrivateRunnableInterface(); private Object elementType; @@ -175,24 +182,24 @@ public abstract class ComputedList extends AbstractObservableList { return doGetList().size(); } - public Object get(int index) { + public E get(int index) { getterCalled(); return doGetList().get(index); } - private final List getList() { + private final List<E> getList() { getterCalled(); return doGetList(); } - final List doGetList() { + final List<E> doGetList() { if (dirty) { // This line will do the following: // - Run the calculate method // - While doing so, add any observable that is touched to the // dependencies list IObservable[] newDependencies = ObservableTracker.runAndMonitor( - privateInterface, privateInterface, null); + privateRunnableInterface, privateChangeInterface, null); // If any dependencies are stale, a stale event will be fired here // even if we were already stale before recomputing. This is in case @@ -207,7 +214,7 @@ public abstract class ComputedList extends AbstractObservableList { if (!stale) { for (int i = 0; i < newDependencies.length; i++) { - newDependencies[i].addStaleListener(privateInterface); + newDependencies[i].addStaleListener(privateStaleInterface); } } @@ -231,7 +238,7 @@ public abstract class ComputedList extends AbstractObservableList { * * @return the object's list. */ - protected abstract List calculate(); + protected abstract List<E> calculate(); private void makeDirty() { if (!dirty) { @@ -242,16 +249,25 @@ public abstract class ComputedList extends AbstractObservableList { stopListening(); // copy the old list - final List oldList = new ArrayList(cachedList); + final List<E> oldList = new ArrayList<E>(cachedList); // Fire the "dirty" event. This implementation recomputes the new // list lazily. - fireListChange(new ListDiff() { - ListDiffEntry[] differences; + fireListChange(new ListDiff<E>() { + List<ListDiffEntry<E>> differences; - public ListDiffEntry[] getDifferences() { + public ListDiffEntry<?>[] getDifferences() { if (differences == null) - differences = Diffs.computeListDiff(oldList, getList()) + return Diffs.computeListDiff(oldList, getList()) .getDifferences(); + return differences.toArray(new ListDiffEntry[differences + .size()]); + } + + @Override + public List<ListDiffEntry<E>> getDifferencesAsList() { + if (differences == null) + differences = Diffs.computeListDiff(oldList, getList()) + .getDifferencesAsList(); return differences; } }); @@ -263,8 +279,8 @@ public abstract class ComputedList extends AbstractObservableList { for (int i = 0; i < dependencies.length; i++) { IObservable observable = dependencies[i]; - observable.removeChangeListener(privateInterface); - observable.removeStaleListener(privateInterface); + observable.removeChangeListener(privateChangeInterface); + observable.removeStaleListener(privateStaleInterface); } dependencies = null; } @@ -294,7 +310,8 @@ public abstract class ComputedList extends AbstractObservableList { computeListForListeners(); } - public synchronized void addListChangeListener(IListChangeListener listener) { + public synchronized void addListChangeListener( + IListChangeListener<E> listener) { super.addListChangeListener(listener); // If somebody is listening, we need to make sure we attach our own // listeners diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/DecoratingObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/DecoratingObservableList.java index e09a3b4f..a4a6f9ec 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/DecoratingObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/DecoratingObservableList.java @@ -21,14 +21,16 @@ import org.eclipse.core.databinding.observable.DecoratingObservableCollection; /** * An observable list which decorates another observable list. * + * @param <E> + * * @since 1.2 */ -public class DecoratingObservableList extends DecoratingObservableCollection - implements IObservableList { +public class DecoratingObservableList<E> extends + DecoratingObservableCollection<E> implements IObservableList<E> { - private IObservableList decorated; + private IObservableList<E> decorated; - private IListChangeListener listChangeListener; + private IListChangeListener<E> listChangeListener; /** * Constructs a DecoratingObservableList which decorates the given @@ -38,25 +40,26 @@ public class DecoratingObservableList extends DecoratingObservableCollection * the observable list being decorated * @param disposeDecoratedOnDispose */ - public DecoratingObservableList(IObservableList decorated, + public DecoratingObservableList(IObservableList<E> decorated, boolean disposeDecoratedOnDispose) { super(decorated, disposeDecoratedOnDispose); this.decorated = decorated; } - public synchronized void addListChangeListener(IListChangeListener listener) { + public synchronized void addListChangeListener( + IListChangeListener<E> listener) { addListener(ListChangeEvent.TYPE, listener); } public synchronized void removeListChangeListener( - IListChangeListener listener) { + IListChangeListener<E> listener) { removeListener(ListChangeEvent.TYPE, listener); } - protected void fireListChange(ListDiff diff) { + protected void fireListChange(ListDiff<E> diff) { // fire general change event first super.fireChange(); - fireEvent(new ListChangeEvent(this, diff)); + fireEvent(new ListChangeEvent<E>(this, diff)); } protected void fireChange() { @@ -66,8 +69,8 @@ public class DecoratingObservableList extends DecoratingObservableCollection protected void firstListenerAdded() { if (listChangeListener == null) { - listChangeListener = new IListChangeListener() { - public void handleListChange(ListChangeEvent event) { + listChangeListener = new IListChangeListener<E>() { + public void handleListChange(ListChangeEvent<E> event) { DecoratingObservableList.this.handleListChange(event); } }; @@ -93,21 +96,21 @@ public class DecoratingObservableList extends DecoratingObservableCollection * @param event * the change event received from the decorated observable */ - protected void handleListChange(final ListChangeEvent event) { + protected void handleListChange(final ListChangeEvent<E> event) { fireListChange(event.diff); } - public void add(int index, Object o) { + public void add(int index, E o) { checkRealm(); decorated.add(index, o); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { checkRealm(); return decorated.addAll(index, c); } - public Object get(int index) { + public E get(int index) { getterCalled(); return decorated.get(index); } @@ -122,16 +125,16 @@ public class DecoratingObservableList extends DecoratingObservableCollection return decorated.lastIndexOf(o); } - public ListIterator listIterator() { + public ListIterator<E> listIterator() { return listIterator(0); } - public ListIterator listIterator(int index) { + public ListIterator<E> listIterator(int index) { getterCalled(); - final ListIterator iterator = decorated.listIterator(index); - return new ListIterator() { + final ListIterator<E> iterator = decorated.listIterator(index); + return new ListIterator<E>() { - public void add(Object o) { + public void add(E o) { iterator.add(o); } @@ -145,7 +148,7 @@ public class DecoratingObservableList extends DecoratingObservableCollection return iterator.hasPrevious(); } - public Object next() { + public E next() { getterCalled(); return iterator.next(); } @@ -155,7 +158,7 @@ public class DecoratingObservableList extends DecoratingObservableCollection return iterator.nextIndex(); } - public Object previous() { + public E previous() { getterCalled(); return iterator.previous(); } @@ -170,29 +173,29 @@ public class DecoratingObservableList extends DecoratingObservableCollection iterator.remove(); } - public void set(Object o) { + public void set(E o) { checkRealm(); iterator.set(o); } }; } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { checkRealm(); return decorated.move(oldIndex, newIndex); } - public Object remove(int index) { + public E remove(int index) { checkRealm(); return decorated.remove(index); } - public Object set(int index, Object element) { + public E set(int index, E element) { checkRealm(); return decorated.set(index, element); } - public List subList(int fromIndex, int toIndex) { + public List<E> subList(int fromIndex, int toIndex) { getterCalled(); return decorated.subList(fromIndex, toIndex); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IListChangeListener.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IListChangeListener.java index 83727299..aa8316e6 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IListChangeListener.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IListChangeListener.java @@ -16,9 +16,11 @@ import org.eclipse.core.databinding.observable.IObservablesListener; /** * Listener for changes to observable lists. * + * @param <E> + * * @since 1.0 */ -public interface IListChangeListener extends IObservablesListener { +public interface IListChangeListener<E> extends IObservablesListener { /** * Handle a change to an observable list. The change is described by the @@ -28,6 +30,6 @@ public interface IListChangeListener extends IObservablesListener { * * @param event */ - void handleListChange(ListChangeEvent event); + void handleListChange(ListChangeEvent<E> event); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IObservableList.java index 858ae238..84c76ad6 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/IObservableList.java @@ -23,6 +23,8 @@ import org.eclipse.core.databinding.observable.IObservableCollection; /** * A list whose changes can be tracked by list change listeners. * + * @param <E> + * * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the framework classes * that implement this interface. Note that direct implementers of @@ -34,106 +36,108 @@ import org.eclipse.core.databinding.observable.IObservableCollection; * * @since 1.0 */ -public interface IObservableList extends List, IObservableCollection { - +public interface IObservableList<E> extends List<E>, IObservableCollection<E> { + /** * Adds the given list change listener to the list of list change listeners. + * * @param listener */ - public void addListChangeListener(IListChangeListener listener); - + public void addListChangeListener(IListChangeListener<E> listener); + /** - * Removes the given list change listener from the list of list change listeners. - * Has no effect if the given listener is not registered as a list change listener. + * Removes the given list change listener from the list of list change + * listeners. Has no effect if the given listener is not registered as a + * list change listener. * * @param listener */ - public void removeListChangeListener(IListChangeListener listener); + public void removeListChangeListener(IListChangeListener<E> listener); /** * @TrackedGetter */ - public int size(); + public int size(); /** * @TrackedGetter */ - public boolean isEmpty(); + public boolean isEmpty(); /** * @TrackedGetter */ - public boolean contains(Object o); + public boolean contains(Object o); /** * @TrackedGetter */ - public Iterator iterator(); + public Iterator<E> iterator(); /** * @TrackedGetter */ - public Object[] toArray(); + public Object[] toArray(); /** * @TrackedGetter */ - public Object[] toArray(Object a[]); + public <T> T[] toArray(T a[]); /** * */ - public boolean add(Object o); + public boolean add(E o); /** * */ - public boolean remove(Object o); + public boolean remove(Object o); /** * @TrackedGetter */ - public boolean containsAll(Collection c); + public boolean containsAll(Collection<?> c); /** * */ - public boolean addAll(Collection c); + public boolean addAll(Collection<? extends E> c); /** * */ - public boolean addAll(int index, Collection c); + public boolean addAll(int index, Collection<? extends E> c); /** * */ - public boolean removeAll(Collection c); + public boolean removeAll(Collection<?> c); /** * */ - public boolean retainAll(Collection c); + public boolean retainAll(Collection<?> c); /** * @TrackedGetter */ - public boolean equals(Object o); + public boolean equals(Object o); /** * @TrackedGetter */ - public int hashCode(); + public int hashCode(); /** * @TrackedGetter */ - public Object get(int index); + public E get(int index); /** * */ - public Object set(int index, Object element); + public E set(int index, E element); /** * Moves the element located at <code>oldIndex</code> to @@ -153,42 +157,43 @@ public interface IObservableList extends List, IObservableCollection { * range <code>0 <= newIndex < size()</code>. * @return the element that was moved. * @throws IndexOutOfBoundsException - * if either argument is out of range (<code>0 <= index < size()</code>). + * if either argument is out of range ( + * <code>0 <= index < size()</code>). * @see ListDiffVisitor#handleMove(int, int, Object) * @see ListDiff#accept(ListDiffVisitor) * @since 1.1 */ - public Object move(int oldIndex, int newIndex); + public E move(int oldIndex, int newIndex); /** * */ - public Object remove(int index); + public E remove(int index); /** * @TrackedGetter */ - public int indexOf(Object o); + public int indexOf(Object o); /** * @TrackedGetter */ - public int lastIndexOf(Object o); + public int lastIndexOf(Object o); /** * @TrackedGetter */ - public ListIterator listIterator(); + public ListIterator<E> listIterator(); /** * @TrackedGetter */ - public ListIterator listIterator(int index); + public ListIterator<E> listIterator(int index); /** * @TrackedGetter */ - public List subList(int fromIndex, int toIndex); + public List<E> subList(int fromIndex, int toIndex); /** * @return the type of the elements or <code>null</code> if untyped diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListChangeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListChangeEvent.java index 1b2ce4d7..1254f89e 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListChangeEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListChangeEvent.java @@ -18,9 +18,11 @@ import org.eclipse.core.databinding.observable.ObservableEvent; * List change event describing an incremental change of an * {@link IObservableList} object. * + * @param <E> + * * @since 1.0 */ -public class ListChangeEvent extends ObservableEvent { +public class ListChangeEvent<E> extends ObservableEvent<ListChangeEvent<E>> { /** * @@ -33,7 +35,13 @@ public class ListChangeEvent extends ObservableEvent { * Description of the change to the source observable list. Listeners must * not change this field. */ - public ListDiff diff; + public ListDiff<E> diff; + + /** + * Always identical to <code>EventObject.source</code> but the type + * information is maintained. + */ + private IObservableList<E> typedSource; /** * Creates a new list change event. @@ -43,8 +51,9 @@ public class ListChangeEvent extends ObservableEvent { * @param diff * the list change */ - public ListChangeEvent(IObservableList source, ListDiff diff) { + public ListChangeEvent(IObservableList<E> source, ListDiff<E> diff) { super(source); + this.typedSource = source; this.diff = diff; } @@ -53,12 +62,12 @@ public class ListChangeEvent extends ObservableEvent { * * @return the observable list from which this event originated */ - public IObservableList getObservableList() { - return (IObservableList) getSource(); + public IObservableList<E> getObservableList() { + return typedSource; } protected void dispatch(IObservablesListener listener) { - ((IListChangeListener) listener).handleListChange(this); + ((IListChangeListener<E>) listener).handleListChange(this); } protected Object getListenerType() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiff.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiff.java index 5d631cb4..f6b5e20b 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiff.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiff.java @@ -13,6 +13,7 @@ package org.eclipse.core.databinding.observable.list; import java.util.AbstractList; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -22,18 +23,58 @@ import org.eclipse.core.internal.databinding.observable.Util; /** * Object describing a diff between two lists. * + * @param <E> + * * @since 1.0 */ -public abstract class ListDiff implements IDiff { +public abstract class ListDiff<E> implements IDiff { /** * Returns a ListDiffEntry array representing the differences in the list, * in the order they are to be processed. + * <P> + * This method returns identical results to + * <code>getDifferencesAsList</code> except that the results are returned as + * a array and so the ListDiffEntry objects are not properly typed. This + * form is here for compatibility. Use <code>getDifferencesAsList</code> to + * get typed results. * * @return a ListDiffEntry array representing the differences in the list, * in the order they are to be processed. */ - public abstract ListDiffEntry[] getDifferences(); + public abstract ListDiffEntry<?>[] getDifferences(); + + /** + * Returns a ListDiffEntry array representing the differences in the list, + * in the order they are to be processed. + * <P> + * This method returns identical results to <code>getDifferences</code> + * except that the results are returned as a <code>List</code> and are + * appropriately typed. + * <P> + * This default implementation returns the list by calling the + * <code>getDifferences</code> method and casting the result in a + * type-unsafe way. Derived classes can override this method to return the + * identical results in a type-safe way. Ultimately it should be required + * that this method be implemented in derived classes. At that time the + * <code>getDifferences</code> method can be deprecated. + * + * @return a ListDiffEntry array representing the differences in the list, + * in the order they are to be processed, may be an empty list but + * never null + * @since 1.5 + */ + public List<ListDiffEntry<E>> getDifferencesAsList() { + // Return result using type-unsafe code + List<ListDiffEntry<E>> result = new ArrayList<ListDiffEntry<E>>(); + if (getDifferences() != null) { + for (ListDiffEntry<?> entry : getDifferences()) { + + result.add((ListDiffEntry<E>) entry); + } + } + return result; + } /** * Traverses the {@link #getDifferences()} array, calling the appropriate @@ -56,22 +97,22 @@ public abstract class ListDiff implements IDiff { * @see ListDiffVisitor * @since 1.1 */ - public void accept(ListDiffVisitor visitor) { - ListDiffEntry[] differences = getDifferences(); - for (int i = 0; i < differences.length; i++) { - ListDiffEntry entry = differences[i]; - Object elem = entry.getElement(); + public void accept(ListDiffVisitor<E> visitor) { + List<ListDiffEntry<E>> differences = getDifferencesAsList(); + for (int i = 0; i < differences.size(); i++) { + ListDiffEntry<E> entry = differences.get(i); + E elem = entry.getElement(); int pos = entry.getPosition(); boolean add = entry.isAddition(); - if (i + 1 < differences.length) { - ListDiffEntry nextEntry = differences[i + 1]; + if (i + 1 < differences.size()) { + ListDiffEntry<E> nextEntry = differences.get(i + 1); if (add != nextEntry.isAddition()) { int addPos; - Object addElem; + E addElem; int removePos; - Object removeElem; + E removeElem; if (add) { addPos = pos; @@ -159,18 +200,17 @@ public abstract class ListDiff implements IDiff { * the list to which the diff will be applied * @since 1.2 */ - public void applyTo(final List list) { - accept(new ListDiffVisitor() { - public void handleAdd(int index, Object element) { + public void applyTo(final List<E> list) { + accept(new ListDiffVisitor<E>() { + public void handleAdd(int index, E element) { list.add(index, element); } - public void handleRemove(int index, Object element) { + public void handleRemove(int index, E element) { list.remove(index); } - public void handleReplace(int index, Object oldElement, - Object newElement) { + public void handleReplace(int index, E oldElement, E newElement) { list.set(index, newElement); } }); @@ -190,37 +230,45 @@ public abstract class ListDiff implements IDiff { * @see #applyTo(List) * @since 1.3 */ - public List simulateOn(List list) { - final List[] result = { list }; - accept(new ListDiffVisitor() { - public void handleAdd(int index, Object element) { - List first = result[0].subList(0, index); - List middle = Collections.singletonList(element); - List last = result[0].subList(index, result[0].size()); - result[0] = ConcatList.cat(first, middle, last); + public List<E> simulateOn(List<E> list) { + class ResultReference { + List<E> value; + } + final ResultReference result = new ResultReference(); + result.value = list; + + accept(new ListDiffVisitor<E>() { + public void handleAdd(int index, E element) { + List<E> first = result.value.subList(0, index); + List<E> middle = Collections.singletonList(element); + List<E> last = result.value.subList(index, result.value.size()); + result.value = ConcatList.cat(first, middle, last); } - public void handleRemove(int index, Object element) { - List first = result[0].subList(0, index); - List last = result[0].subList(index + 1, result[0].size()); - result[0] = ConcatList.cat(first, last); + public void handleRemove(int index, E element) { + List<E> first = result.value.subList(0, index); + List<E> last = result.value.subList(index + 1, + result.value.size()); + result.value = ConcatList.cat(first, last); } - public void handleReplace(int index, Object oldElement, - Object newElement) { - List first = result[0].subList(0, index); - List middle = Collections.singletonList(newElement); - List last = result[0].subList(index + 1, result[0].size()); - result[0] = ConcatList.cat(first, middle, last); + public void handleReplace(int index, E oldElement, E newElement) { + List<E> first = result.value.subList(0, index); + List<E> middle = Collections.singletonList(newElement); + List<E> last = result.value.subList(index + 1, + result.value.size()); + result.value = ConcatList.cat(first, middle, last); } }); - return result[0]; + return result.value; } - private static class ConcatList extends AbstractList { - private final List[] subLists; + private static class ConcatList<E> extends AbstractList<E> { + private final List<E> firstSublist; + private final List<E> middleSublist; + private final List<E> lastSublist; - public static List cat(List a, List b, List c) { + public static <T> List<T> cat(List<T> a, List<T> b, List<T> c) { if (a.isEmpty()) { return cat(b, c); } else if (b.isEmpty()) { @@ -228,43 +276,49 @@ public abstract class ListDiff implements IDiff { } else if (c.isEmpty()) { return cat(a, b); } - return new ConcatList(new List[] { a, b, c }); + return new ConcatList<T>(a, b, c); } - public static List cat(List a, List b) { + public static <T> List<T> cat(List<T> a, List<T> b) { if (a.isEmpty()) { if (b.isEmpty()) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } return b; } else if (b.isEmpty()) { return a; } - return new ConcatList(new List[] { a, b }); + List<T> c = Collections.emptyList(); + return new ConcatList<T>(a, b, c); } - private ConcatList(List[] sublists) { - this.subLists = sublists; + private ConcatList(List<E> firstSublist, List<E> middleSublist, + List<E> lastSublist) { + this.firstSublist = firstSublist; + this.middleSublist = middleSublist; + this.lastSublist = lastSublist; } - public Object get(int index) { - int offset = 0; - for (int i = 0; i < subLists.length; i++) { - int subListIndex = index - offset; - if (subListIndex < subLists[i].size()) { - return subLists[i].get(subListIndex); - } - offset += subLists[i].size(); + public E get(int index) { + int subListIndex = index; + if (subListIndex < firstSublist.size()) { + return firstSublist.get(subListIndex); } + subListIndex -= firstSublist.size(); + if (subListIndex < middleSublist.size()) { + return middleSublist.get(subListIndex); + } + subListIndex -= middleSublist.size(); + if (subListIndex < lastSublist.size()) { + return lastSublist.get(subListIndex); + } + throw new IndexOutOfBoundsException(); } public int size() { - int size = 0; - for (int i = 0; i < subLists.length; i++) { - size += subLists[i].size(); - } - return size; + return firstSublist.size() + middleSublist.size() + + lastSublist.size(); } } @@ -272,24 +326,24 @@ public abstract class ListDiff implements IDiff { * @see java.lang.Object#toString() */ public String toString() { - ListDiffEntry[] differences = getDifferences(); + List<ListDiffEntry<E>> differences = getDifferencesAsList(); StringBuffer buffer = new StringBuffer(); buffer.append(getClass().getName()); - if (differences == null || differences.length == 0) { + if (differences == null || differences.size() == 0) { buffer.append("{}"); //$NON-NLS-1$ } else { buffer.append("{"); //$NON-NLS-1$ - for (int i = 0; i < differences.length; i++) { + for (int i = 0; i < differences.size(); i++) { if (i > 0) buffer.append(", "); //$NON-NLS-1$ buffer.append("difference[") //$NON-NLS-1$ - .append(i).append("] [") //$NON-NLS-1$ - .append( - differences[i] != null ? differences[i] - .toString() : "null") //$NON-NLS-1$ + .append(i) + .append("] [") //$NON-NLS-1$ + .append(differences.get(i) != null ? differences.get(i) + .toString() : "null") //$NON-NLS-1$ .append("]"); //$NON-NLS-1$ } buffer.append("}"); //$NON-NLS-1$ diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffEntry.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffEntry.java index da2e79ff..616f8efc 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffEntry.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffEntry.java @@ -12,42 +12,43 @@ package org.eclipse.core.databinding.observable.list; /** - * A single addition of an element to a list or removal of an element from a list. - * + * A single addition of an element to a list or removal of an element from a + * list. + * + * @param <E> + * * @since 1.0 */ -public abstract class ListDiffEntry { - +public abstract class ListDiffEntry<E> { + /** * @return the 0-based position of the addition or removal */ public abstract int getPosition(); - + /** - * @return true if this represents an addition, false if this represents a removal + * @return true if this represents an addition, false if this represents a + * removal */ public abstract boolean isAddition(); - + /** * @return the element that was added or removed */ - public abstract Object getElement(); - + public abstract E getElement(); + /** * @see java.lang.Object#toString() */ public String toString() { StringBuffer buffer = new StringBuffer(); - buffer - .append(this.getClass().getName()) - .append("{position [") //$NON-NLS-1$ - .append(getPosition()) - .append("], isAddition [") //$NON-NLS-1$ - .append(isAddition()) - .append("], element [") //$NON-NLS-1$ - .append(getElement() != null ? getElement().toString() : "null") //$NON-NLS-1$ - .append("]}"); //$NON-NLS-1$ - + buffer.append(this.getClass().getName()).append("{position [") //$NON-NLS-1$ + .append(getPosition()).append("], isAddition [") //$NON-NLS-1$ + .append(isAddition()) + .append("], element [") //$NON-NLS-1$ + .append(getElement() != null ? getElement().toString() : "null") //$NON-NLS-1$ + .append("]}"); //$NON-NLS-1$ + return buffer.toString(); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffVisitor.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffVisitor.java index acbd89f9..e81ec5d3 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffVisitor.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ListDiffVisitor.java @@ -16,10 +16,12 @@ import java.util.List; /** * A visitor for processing differences in a ListDiff. * + * @param <E> + * * @see ListDiff#accept(ListDiffVisitor) * @since 1.1 */ -public abstract class ListDiffVisitor { +public abstract class ListDiffVisitor<E> { /** * Notifies the visitor that <code>element</code> was added to the list at * position <code>index</code>. @@ -29,22 +31,22 @@ public abstract class ListDiffVisitor { * @param element * the element that was added */ - public abstract void handleAdd(int index, Object element); + public abstract void handleAdd(int index, E element); /** - * Notifies the visitor that <code>element</code> was removed from the - * list at position <code>index</code>. + * Notifies the visitor that <code>element</code> was removed from the list + * at position <code>index</code>. * * @param index * the index where the element was removed * @param element * the element that was removed */ - public abstract void handleRemove(int index, Object element); + public abstract void handleRemove(int index, E element); /** - * Notifies the visitor that <code>element</code> was moved in the list - * from position <code>oldIndex</code> to position <code>newIndex</code>. + * Notifies the visitor that <code>element</code> was moved in the list from + * position <code>oldIndex</code> to position <code>newIndex</code>. * <p> * The default implementation of this method calls * {@link #handleRemove(int, Object)} with the old position, then @@ -60,7 +62,7 @@ public abstract class ListDiffVisitor { * the element that was moved * @see IObservableList#move(int, int) */ - public void handleMove(int oldIndex, int newIndex, Object element) { + public void handleMove(int oldIndex, int newIndex, E element) { handleRemove(oldIndex, element); handleAdd(newIndex, element); } @@ -83,7 +85,7 @@ public abstract class ListDiffVisitor { * the element that replaced oldElement. * @see List#set(int, Object) */ - public void handleReplace(int index, Object oldElement, Object newElement) { + public void handleReplace(int index, E oldElement, E newElement) { handleRemove(index, oldElement); handleAdd(index, newElement); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/MultiList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/MultiList.java index 453fcc71..7a95e0ad 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/MultiList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/MultiList.java @@ -11,7 +11,8 @@ package org.eclipse.core.databinding.observable.list; -import java.lang.reflect.Array; +//import java.lang.reflect.Array; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -30,13 +31,15 @@ import org.eclipse.core.runtime.Assert; * {@link #set(int, Object)} method. All other mutator methods (addition methods * and {@link #move(int, int)}) throw an {@link UnsupportedOperationException}. * + * @param <E> + * * @since 1.2 */ -public class MultiList extends AbstractObservableList { - private IObservableList[] lists; +public class MultiList<E> extends AbstractObservableList<E> { + private List<IObservableList<E>> lists; private Object elementType; - private IListChangeListener listChangeListener; + private IListChangeListener<E> listChangeListener; private IStaleListener staleListener; private Boolean stale; @@ -46,8 +49,22 @@ public class MultiList extends AbstractObservableList { * * @param lists * the array of observable lists backing this MultiList. + * @deprecated use MultiList(List<IObservableList<E>>) instead */ - public MultiList(IObservableList[] lists) { + @Deprecated + public MultiList(IObservableList<E>[] lists) { + this(Realm.getDefault(), lists, null); + } + + /** + * Constructs a MultiList in the default realm, and backed by the given + * observable lists. + * + * @param lists + * the array of observable lists backing this MultiList. + * @since 1.5 + */ + public MultiList(List<IObservableList<E>> lists) { this(Realm.getDefault(), lists, null); } @@ -59,8 +76,24 @@ public class MultiList extends AbstractObservableList { * the array of observable lists backing this MultiList. * @param elementType * element type of the constructed list. + * @deprecated use MultiList(List<IObservableList<E>>, Object) instead */ - public MultiList(IObservableList[] lists, Object elementType) { + @Deprecated + public MultiList(IObservableList<E>[] lists, Object elementType) { + this(Realm.getDefault(), lists, elementType); + } + + /** + * Constructs a MultiList in the default realm backed by the given + * observable lists. + * + * @param lists + * the array of observable lists backing this MultiList. + * @param elementType + * element type of the constructed list. + * @since 1.5 + */ + public MultiList(List<IObservableList<E>> lists, Object elementType) { this(Realm.getDefault(), lists, elementType); } @@ -73,7 +106,7 @@ public class MultiList extends AbstractObservableList { * @param lists * the array of observable lists backing this MultiList */ - public MultiList(Realm realm, IObservableList[] lists) { + public MultiList(Realm realm, IObservableList<E>[] lists) { this(realm, lists, null); } @@ -87,23 +120,52 @@ public class MultiList extends AbstractObservableList { * the array of observable lists backing this MultiList * @param elementType * element type of the constructed list. + * @deprecated use MultiList(realm, List<IObservableList<E>>, Object) + * instead */ - public MultiList(Realm realm, IObservableList[] lists, Object elementType) { + @Deprecated + public MultiList(Realm realm, IObservableList<E>[] lists, Object elementType) { super(realm); - this.lists = lists; + this.lists = new ArrayList<IObservableList<E>>(lists.length); + for (IObservableList<E> list : lists) { + this.lists.add(list); + } this.elementType = elementType; for (int i = 0; i < lists.length; i++) { - Assert - .isTrue(realm.equals(lists[i].getRealm()), - "All source lists in a MultiList must belong to the same realm"); //$NON-NLS-1$ + Assert.isTrue(realm.equals(lists[i].getRealm()), + "All source lists in a MultiList must belong to the same realm"); //$NON-NLS-1$ + } + } + + /** + * Constructs a MultiList belonging to the given realm, and backed by the + * given observable lists. + * + * @param realm + * the observable's realm + * @param lists + * the array of observable lists backing this MultiList + * @param elementType + * element type of the constructed list. + * @since 1.5 + */ + public MultiList(Realm realm, List<IObservableList<E>> lists, + Object elementType) { + super(realm); + this.lists = lists; + this.elementType = elementType; + + for (IObservableList<E> list : lists) { + Assert.isTrue(realm.equals(list.getRealm()), + "All source lists in a MultiList must belong to the same realm"); //$NON-NLS-1$ } } protected void firstListenerAdded() { if (listChangeListener == null) { - listChangeListener = new IListChangeListener() { - public void handleListChange(final ListChangeEvent event) { + listChangeListener = new IListChangeListener<E>() { + public void handleListChange(final ListChangeEvent<E> event) { getRealm().exec(new Runnable() { public void run() { stale = null; @@ -127,9 +189,9 @@ public class MultiList extends AbstractObservableList { }; } - for (int i = 0; i < lists.length; i++) { - lists[i].addListChangeListener(listChangeListener); - lists[i].addStaleListener(staleListener); + for (IObservableList<E> list : lists) { + list.addListChangeListener(listChangeListener); + list.addStaleListener(staleListener); // Determining staleness at this time prevents firing redundant // stale events if MultiList happens to be stale now, and a sublist @@ -140,14 +202,14 @@ public class MultiList extends AbstractObservableList { protected void lastListenerRemoved() { if (listChangeListener != null) { - for (int i = 0; i < lists.length; i++) { - lists[i].removeListChangeListener(listChangeListener); + for (IObservableList<E> list : lists) { + list.removeListChangeListener(listChangeListener); } listChangeListener = null; } if (staleListener != null) { - for (int i = 0; i < lists.length; i++) { - lists[i].removeStaleListener(staleListener); + for (IObservableList<E> list : lists) { + list.removeStaleListener(staleListener); } staleListener = null; } @@ -161,45 +223,47 @@ public class MultiList extends AbstractObservableList { } } - private void listChanged(ListChangeEvent event) { - IObservableList source = event.getObservableList(); + private void listChanged(ListChangeEvent<E> event) { + IObservableList<E> source = event.getObservableList(); int offset = 0; - for (int i = 0; i < lists.length; i++) { - if (source == lists[i]) { + for (IObservableList<E> list : lists) { + if (source == list) { fireListChange(offsetListDiff(offset, event.diff)); return; } - offset += lists[i].size(); + offset += list.size(); } - Assert - .isLegal( - false, - "MultiList received a ListChangeEvent from an observable list that is not one of its sources."); //$NON-NLS-1$ + Assert.isLegal( + false, + "MultiList received a ListChangeEvent from an observable list that is not one of its sources."); //$NON-NLS-1$ } - private ListDiff offsetListDiff(int offset, ListDiff diff) { - return Diffs.createListDiff(offsetListDiffEntries(offset, diff - .getDifferences())); + private ListDiff<E> offsetListDiff(int offset, ListDiff<E> diff) { + return Diffs.createListDiff(offsetListDiffEntries(offset, + diff.getDifferencesAsList())); } - private ListDiffEntry[] offsetListDiffEntries(int offset, - ListDiffEntry[] entries) { - ListDiffEntry[] offsetEntries = new ListDiffEntry[entries.length]; - for (int i = 0; i < entries.length; i++) { - offsetEntries[i] = offsetListDiffEntry(offset, entries[i]); + private List<ListDiffEntry<E>> offsetListDiffEntries(int offset, + List<ListDiffEntry<E>> entries) { + List<ListDiffEntry<E>> offsetEntries = new ArrayList<ListDiffEntry<E>>( + entries.size()); + for (ListDiffEntry<E> entry : entries) { + offsetEntries.add(offsetListDiffEntry(offset, entry)); } return offsetEntries; } - private ListDiffEntry offsetListDiffEntry(int offset, ListDiffEntry entry) { - return Diffs.createListDiffEntry(offset + entry.getPosition(), entry - .isAddition(), entry.getElement()); + private ListDiffEntry<E> offsetListDiffEntry(int offset, + ListDiffEntry<E> entry) { + return Diffs.createListDiffEntry(offset + entry.getPosition(), + entry.isAddition(), entry.getElement()); } protected int doGetSize() { int size = 0; - for (int i = 0; i < lists.length; i++) - size += lists[i].size(); + for (IObservableList<E> list : lists) { + size += list.size(); + } return size; } @@ -215,27 +279,28 @@ public class MultiList extends AbstractObservableList { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { throw new UnsupportedOperationException(); } public void clear() { checkRealm(); - for (int i = 0; i < lists.length; i++) - lists[i].clear(); + for (IObservableList<E> list : lists) { + list.clear(); + } } - public Object get(int index) { + public E get(int index) { getterCalled(); int offset = 0; - for (int i = 0; i < lists.length; i++) { - if (index - offset < lists[i].size()) - return lists[i].get(index - offset); - offset += lists[i].size(); + for (IObservableList<E> list : lists) { + if (index - offset < list.size()) + return list.get(index - offset); + offset += list.size(); } throw new IndexOutOfBoundsException("index: " + index + ", size: " //$NON-NLS-1$ //$NON-NLS-2$ + offset); @@ -243,8 +308,8 @@ public class MultiList extends AbstractObservableList { public boolean contains(Object o) { getterCalled(); - for (int i = 0; i < lists.length; i++) { - if (lists[i].contains(o)) + for (IObservableList<E> list : lists) { + if (list.contains(o)) return true; } return false; @@ -258,18 +323,18 @@ public class MultiList extends AbstractObservableList { return false; if (!(o instanceof List)) return false; - List that = (List) o; + List<?> that = (List<?>) o; if (doGetSize() != that.size()) return false; int subListIndex = 0; - for (int i = 0; i < lists.length; i++) { - List subList = that.subList(subListIndex, subListIndex - + lists[i].size()); - if (!lists[i].equals(subList)) { + for (IObservableList<E> list : lists) { + List<?> subList = that.subList(subListIndex, + subListIndex + list.size()); + if (!list.equals(subList)) { return false; } - subListIndex += lists[i].size(); + subListIndex += list.size(); } return true; } @@ -277,8 +342,8 @@ public class MultiList extends AbstractObservableList { public int hashCode() { getterCalled(); int result = 1; - for (int i = 0; i < lists.length; i++) { - result = result * 31 + lists[i].hashCode(); + for (IObservableList<E> list : lists) { + result = result * 31 + list.hashCode(); } return result; } @@ -286,25 +351,26 @@ public class MultiList extends AbstractObservableList { public int indexOf(Object o) { getterCalled(); int offset = 0; - for (int i = 0; i < lists.length; i++) { - int index = lists[i].indexOf(o); + for (IObservableList<E> list : lists) { + int index = list.indexOf(o); if (index != -1) return offset + index; - offset += lists[i].size(); + offset += list.size(); } return -1; } public boolean isEmpty() { getterCalled(); - for (int i = 0; i < lists.length; i++) { - if (!lists[i].isEmpty()) + for (IObservableList<E> list : lists) { + if (!list.isEmpty()) { return false; + } } return true; } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); return new MultiListItr(); } @@ -312,21 +378,21 @@ public class MultiList extends AbstractObservableList { public int lastIndexOf(Object o) { getterCalled(); int offset = size(); - for (int i = 0; i < lists.length; i++) { - offset -= lists[i].size(); - int index = lists[i].indexOf(o); + for (IObservableList<E> list : lists) { + offset -= list.size(); + int index = list.indexOf(o); if (index != -1) return offset + index; } return -1; } - public ListIterator listIterator(int index) { + public ListIterator<E> listIterator(int index) { getterCalled(); return new MultiListListItr(index); } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { throw new UnsupportedOperationException(); } @@ -340,41 +406,41 @@ public class MultiList extends AbstractObservableList { return false; } - public Object remove(int index) { + public E remove(int index) { int offset = 0; - for (int i = 0; i < lists.length; i++) { - if (index - offset < lists[i].size()) { - return lists[i].remove(index - offset); + for (IObservableList<E> list : lists) { + if (index - offset < list.size()) { + return list.remove(index - offset); } - offset += lists[i].size(); + offset += list.size(); } throw new IndexOutOfBoundsException("index: " + index + ", size: " //$NON-NLS-1$ //$NON-NLS-2$ + offset); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { boolean changed = false; - for (int i = 0; i < lists.length; i++) { - changed = changed | lists[i].removeAll(c); + for (IObservableList<E> list : lists) { + changed = changed | list.removeAll(c); } return changed; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { boolean changed = false; - for (int i = 0; i < lists.length; i++) { - changed = changed | lists[i].retainAll(c); + for (IObservableList<E> list : lists) { + changed = changed | list.retainAll(c); } return changed; } - public Object set(int index, Object o) { + public E set(int index, E o) { int offset = 0; - for (int i = 0; i < lists.length; i++) { - if (index - offset < lists[i].size()) { - return lists[i].set(index - offset, o); + for (IObservableList<E> list : lists) { + if (index - offset < list.size()) { + return list.set(index - offset, o); } - offset += lists[i].size(); + offset += list.size(); } throw new IndexOutOfBoundsException("index: " + index + ", size: " //$NON-NLS-1$ //$NON-NLS-2$ + offset); @@ -385,21 +451,22 @@ public class MultiList extends AbstractObservableList { return toArray(new Object[doGetSize()]); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); - Object[] result = a; - if (result.length < doGetSize()) { - result = (Object[]) Array.newInstance(a.getClass() - .getComponentType(), doGetSize()); - } - int offset = 0; - for (int i = 0; i < lists.length; i++) { - Object[] oa = lists[i].toArray(); - System.arraycopy(oa, 0, result, offset, oa.length); - offset += lists[i].size(); - } - - return result; + return super.toArray(a); + // T[] result = a; + // if (result.length < doGetSize()) { + // result = (T[]) Array.newInstance(a.getClass().getComponentType(), + // doGetSize()); + // } + // int offset = 0; + // for (IObservableList<E> list : lists) { + // Object[] oa = list.toArray(); + // System.arraycopy(oa, 0, result, offset, oa.length); + // offset += list.size(); + // } + // + // return result; } public boolean isStale() { @@ -421,8 +488,8 @@ public class MultiList extends AbstractObservableList { private boolean computeStaleness() { boolean stale = false; - for (int i = 0; i < lists.length; i++) { - if (lists[i].isStale()) { + for (IObservableList<E> list : lists) { + if (list.isStale()) { stale = true; break; } @@ -437,13 +504,13 @@ public class MultiList extends AbstractObservableList { public synchronized void dispose() { if (lists != null) { if (listChangeListener != null) { - for (int i = 0; i < lists.length; i++) { - lists[i].removeListChangeListener(listChangeListener); + for (IObservableList<E> list : lists) { + list.removeListChangeListener(listChangeListener); } } if (staleListener != null) { - for (int i = 0; i < lists.length; i++) { - lists[i].removeStaleListener(staleListener); + for (IObservableList<E> list : lists) { + list.removeStaleListener(staleListener); } } } @@ -455,29 +522,29 @@ public class MultiList extends AbstractObservableList { super.dispose(); } - private final class MultiListItr implements Iterator { - Iterator[] iters; + private final class MultiListItr implements Iterator<E> { + List<Iterator<E>> iters; int iterIndex = 0; MultiListItr() { - iters = new Iterator[lists.length]; - for (int i = 0; i < lists.length; i++) { - iters[i] = lists[i].iterator(); + iters = new ArrayList<Iterator<E>>(lists.size()); + for (IObservableList<E> list : lists) { + iters.add(list.iterator()); } } public boolean hasNext() { - for (int i = iterIndex; i < iters.length; i++) { - if (iters[i].hasNext()) + for (int i = iterIndex; i < iters.size(); i++) { + if (iters.get(i).hasNext()) return true; } return false; } - public Object next() { - while (iterIndex < iters.length && !iters[iterIndex].hasNext()) + public E next() { + while (iterIndex < iters.size() && !iters.get(iterIndex).hasNext()) iterIndex++; - return iters[iterIndex].next(); + return iters.get(iterIndex).next(); } public void remove() { @@ -485,28 +552,29 @@ public class MultiList extends AbstractObservableList { } } - private class MultiListListItr implements ListIterator { - ListIterator[] iters; + private class MultiListListItr implements ListIterator<E> { + List<ListIterator<E>> iters; int iterIndex; private MultiListListItr(int initialIndex) { - iters = new ListIterator[lists.length]; + iters = new ArrayList<ListIterator<E>>(lists.size()); int offset = 0; - for (int i = 0; i < lists.length; i++) { + for (int i = 0; i < lists.size(); i++) { + IObservableList<E> list = lists.get(i); if (offset <= initialIndex) { - if (offset + lists[i].size() > initialIndex) { + if (offset + list.size() > initialIndex) { // current list contains initial index - iters[i] = lists[i].listIterator(initialIndex - offset); + iters.add(list.listIterator(initialIndex - offset)); iterIndex = i; } else { // current list ends before initial index - iters[i] = lists[i].listIterator(lists[i].size()); + iters.add(list.listIterator(list.size())); } } else { // current list begins after initial index - iters[i] = lists[i].listIterator(); + iters.add(list.listIterator()); } - offset += lists[i].size(); + offset += list.size(); } } @@ -515,8 +583,8 @@ public class MultiList extends AbstractObservableList { } public boolean hasNext() { - for (int i = iterIndex; i < iters.length; i++) { - if (iters[i].hasNext()) + for (int i = iterIndex; i < iters.size(); i++) { + if (iters.get(i).hasNext()) return true; } return false; @@ -524,44 +592,44 @@ public class MultiList extends AbstractObservableList { public boolean hasPrevious() { for (int i = iterIndex; i >= 0; i--) { - if (iters[i].hasPrevious()) + if (iters.get(i).hasPrevious()) return true; } return false; } - public Object next() { - while (iterIndex < iters.length && !iters[iterIndex].hasNext()) + public E next() { + while (iterIndex < iters.size() && !iters.get(iterIndex).hasNext()) iterIndex++; - return iters[iterIndex].next(); + return iters.get(iterIndex).next(); } public int nextIndex() { int offset = 0; for (int i = 0; i < iterIndex; i++) - offset += iters[i].nextIndex(); - return offset + iters[iterIndex].nextIndex(); + offset += iters.get(i).nextIndex(); + return offset + iters.get(iterIndex).nextIndex(); } - public Object previous() { - while (iterIndex >= 0 && !iters[iterIndex].hasPrevious()) + public E previous() { + while (iterIndex >= 0 && !iters.get(iterIndex).hasPrevious()) iterIndex--; - return iters[iterIndex].previous(); + return iters.get(iterIndex).previous(); } public int previousIndex() { int offset = 0; for (int i = 0; i < iterIndex; i++) - offset += iters[i].nextIndex(); - return offset + iters[iterIndex].previousIndex(); + offset += iters.get(i).nextIndex(); + return offset + iters.get(iterIndex).previousIndex(); } public void remove() { throw new UnsupportedOperationException(); } - public void set(Object o) { - iters[iterIndex].set(o); + public void set(E o) { + iters.get(iterIndex).set(o); } } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ObservableList.java index be1ffe92..655970d3 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ObservableList.java @@ -33,13 +33,15 @@ import org.eclipse.core.databinding.observable.Realm; * listeners may be invoked from any thread. * </p> * + * @param <E> + * * @since 1.0 * */ -public abstract class ObservableList extends AbstractObservable implements - IObservableList { +public abstract class ObservableList<E> extends AbstractObservable implements + IObservableList<E> { - protected List wrappedList; + protected List<E> wrappedList; /** * Stale state of the list. Access must occur in the current realm. @@ -48,29 +50,31 @@ public abstract class ObservableList extends AbstractObservable implements private Object elementType; - protected ObservableList(List wrappedList, Object elementType) { + protected ObservableList(List<E> wrappedList, Object elementType) { this(Realm.getDefault(), wrappedList, elementType); } - protected ObservableList(Realm realm, List wrappedList, Object elementType) { + protected ObservableList(Realm realm, List<E> wrappedList, + Object elementType) { super(realm); this.wrappedList = wrappedList; this.elementType = elementType; } - public synchronized void addListChangeListener(IListChangeListener listener) { + public synchronized void addListChangeListener( + IListChangeListener<E> listener) { addListener(ListChangeEvent.TYPE, listener); } public synchronized void removeListChangeListener( - IListChangeListener listener) { + IListChangeListener<E> listener) { removeListener(ListChangeEvent.TYPE, listener); } - protected void fireListChange(ListDiff diff) { + protected void fireListChange(ListDiff<E> diff) { // fire general change event first super.fireChange(); - fireEvent(new ListChangeEvent(this, diff)); + fireEvent(new ListChangeEvent<E>(this, diff)); } public boolean contains(Object o) { @@ -78,7 +82,7 @@ public abstract class ObservableList extends AbstractObservable implements return wrappedList.contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return wrappedList.containsAll(c); } @@ -98,10 +102,10 @@ public abstract class ObservableList extends AbstractObservable implements return wrappedList.isEmpty(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - final Iterator wrappedIterator = wrappedList.iterator(); - return new Iterator() { + final Iterator<E> wrappedIterator = wrappedList.iterator(); + return new Iterator<E>() { public void remove() { throw new UnsupportedOperationException(); @@ -111,7 +115,7 @@ public abstract class ObservableList extends AbstractObservable implements return wrappedIterator.hasNext(); } - public Object next() { + public E next() { return wrappedIterator.next(); } }; @@ -127,7 +131,7 @@ public abstract class ObservableList extends AbstractObservable implements return wrappedList.toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); return wrappedList.toArray(a); } @@ -140,7 +144,7 @@ public abstract class ObservableList extends AbstractObservable implements /** * @TrackedGetter */ - public Object get(int index) { + public E get(int index) { getterCalled(); return wrappedList.get(index); } @@ -166,17 +170,17 @@ public abstract class ObservableList extends AbstractObservable implements /** * @TrackedGetter */ - public ListIterator listIterator() { + public ListIterator<E> listIterator() { return listIterator(0); } /** * @TrackedGetter */ - public ListIterator listIterator(int index) { + public ListIterator<E> listIterator(int index) { getterCalled(); - final ListIterator wrappedIterator = wrappedList.listIterator(index); - return new ListIterator() { + final ListIterator<E> wrappedIterator = wrappedList.listIterator(index); + return new ListIterator<E>() { public int nextIndex() { return wrappedIterator.nextIndex(); @@ -198,36 +202,36 @@ public abstract class ObservableList extends AbstractObservable implements return wrappedIterator.hasPrevious(); } - public Object next() { + public E next() { return wrappedIterator.next(); } - public Object previous() { + public E previous() { return wrappedIterator.previous(); } - public void add(Object o) { + public void add(E o) { throw new UnsupportedOperationException(); } - public void set(Object o) { + public void set(E o) { throw new UnsupportedOperationException(); } }; } - public List subList(final int fromIndex, final int toIndex) { + public List<E> subList(final int fromIndex, final int toIndex) { getterCalled(); if (fromIndex < 0 || fromIndex > toIndex || toIndex > size()) { throw new IndexOutOfBoundsException(); } - return new AbstractObservableList(getRealm()) { + return new AbstractObservableList<E>(getRealm()) { public Object getElementType() { return ObservableList.this.getElementType(); } - public Object get(int location) { + public E get(int location) { return ObservableList.this.get(fromIndex + location); } @@ -241,7 +245,7 @@ public abstract class ObservableList extends AbstractObservable implements ObservableTracker.getterCalled(this); } - public Object set(int index, Object element) { + public E set(int index, E element) { throw new UnsupportedOperationException(); } @@ -269,7 +273,7 @@ public abstract class ObservableList extends AbstractObservable implements * @see ListDiff#accept(ListDiffVisitor) * @since 1.1 */ - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { checkRealm(); int size = wrappedList.size(); if (oldIndex < 0 || oldIndex >= size) @@ -278,28 +282,28 @@ public abstract class ObservableList extends AbstractObservable implements if (newIndex < 0 || newIndex >= size) throw new IndexOutOfBoundsException( "newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ - Object element = remove(oldIndex); + E element = remove(oldIndex); add(newIndex, element); return element; } - public Object remove(int index) { + public E remove(int index) { throw new UnsupportedOperationException(); } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } - public void add(int index, Object element) { + public void add(int index, E element) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { throw new UnsupportedOperationException(); } @@ -307,11 +311,11 @@ public abstract class ObservableList extends AbstractObservable implements throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -360,9 +364,9 @@ public abstract class ObservableList extends AbstractObservable implements return elementType; } - protected void updateWrappedList(List newList) { - List oldList = wrappedList; - ListDiff listDiff = Diffs.computeListDiff(oldList, newList); + protected void updateWrappedList(List<E> newList) { + List<E> oldList = wrappedList; + ListDiff<E> listDiff = Diffs.computeListDiff(oldList, newList); wrappedList = newList; fireListChange(listDiff); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/WritableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/WritableList.java index 7d447a59..bc9a2f5d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/WritableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/WritableList.java @@ -34,9 +34,11 @@ import org.eclipse.core.databinding.observable.Realm; * listeners may be invoked from any thread. * </p> * + * @param <E> + * * @since 1.0 */ -public class WritableList extends ObservableList { +public class WritableList<E> extends ObservableList<E> { /** * Creates an empty writable list in the default realm with a @@ -54,7 +56,7 @@ public class WritableList extends ObservableList { * the observable's realm */ public WritableList(Realm realm) { - this(realm, new ArrayList(), null); + this(realm, new ArrayList<E>(), null); } /** @@ -69,7 +71,7 @@ public class WritableList extends ObservableList { * @param elementType * can be <code>null</code> */ - public WritableList(List toWrap, Object elementType) { + public WritableList(List<E> toWrap, Object elementType) { this(Realm.getDefault(), toWrap, elementType); } @@ -84,8 +86,8 @@ public class WritableList extends ObservableList { * can be <code>null</code> * @since 1.2 */ - public WritableList(Collection collection, Object elementType) { - this(Realm.getDefault(), new ArrayList(collection), elementType); + public WritableList(Collection<E> collection, Object elementType) { + this(Realm.getDefault(), new ArrayList<E>(collection), elementType); } /** @@ -103,7 +105,7 @@ public class WritableList extends ObservableList { * @param elementType * can be <code>null</code> */ - public WritableList(Realm realm, List toWrap, Object elementType) { + public WritableList(Realm realm, List<E> toWrap, Object elementType) { super(realm, toWrap, elementType); } @@ -120,13 +122,14 @@ public class WritableList extends ObservableList { * can be <code>null</code> * @since 1.2 */ - public WritableList(Realm realm, Collection collection, Object elementType) { - super(realm, new ArrayList(collection), elementType); + public WritableList(Realm realm, Collection<E> collection, + Object elementType) { + super(realm, new ArrayList<E>(collection), elementType); } - public Object set(int index, Object element) { + public E set(int index, E element) { checkRealm(); - Object oldElement = wrappedList.set(index, element); + E oldElement = wrappedList.set(index, element); fireListChange(Diffs.createListDiff( Diffs.createListDiffEntry(index, false, oldElement), Diffs.createListDiffEntry(index, true, element))); @@ -136,7 +139,7 @@ public class WritableList extends ObservableList { /** * @since 1.1 */ - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { checkRealm(); int size = wrappedList.size(); if (oldIndex < 0 || oldIndex >= size) @@ -147,7 +150,7 @@ public class WritableList extends ObservableList { "newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ if (oldIndex == newIndex) return wrappedList.get(oldIndex); - Object element = wrappedList.remove(oldIndex); + E element = wrappedList.remove(oldIndex); wrappedList.add(newIndex, element); fireListChange(Diffs.createListDiff( Diffs.createListDiffEntry(oldIndex, false, element), @@ -155,15 +158,15 @@ public class WritableList extends ObservableList { return element; } - public Object remove(int index) { + public E remove(int index) { checkRealm(); - Object oldElement = wrappedList.remove(index); + E oldElement = wrappedList.remove(index); fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index, false, oldElement))); return oldElement; } - public boolean add(Object element) { + public boolean add(E element) { checkRealm(); boolean added = wrappedList.add(element); if (added) { @@ -173,35 +176,35 @@ public class WritableList extends ObservableList { return added; } - public void add(int index, Object element) { + public void add(int index, E element) { checkRealm(); wrappedList.add(index, element); fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index, true, element))); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { checkRealm(); - ListDiffEntry[] entries = new ListDiffEntry[c.size()]; - int i = 0; + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>( + c.size()); int addIndex = wrappedList.size(); - for (Iterator it = c.iterator(); it.hasNext();) { - Object element = it.next(); - entries[i++] = Diffs.createListDiffEntry(addIndex++, true, element); + for (Iterator<? extends E> it = c.iterator(); it.hasNext();) { + E element = it.next(); + entries.add(Diffs.createListDiffEntry(addIndex++, true, element)); } boolean added = wrappedList.addAll(c); fireListChange(Diffs.createListDiff(entries)); return added; } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { checkRealm(); - ListDiffEntry[] entries = new ListDiffEntry[c.size()]; - int i = 0; + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>( + c.size()); int addIndex = index; - for (Iterator it = c.iterator(); it.hasNext();) { - Object element = it.next(); - entries[i++] = Diffs.createListDiffEntry(addIndex++, true, element); + for (Iterator<? extends E> it = c.iterator(); it.hasNext();) { + E element = it.next(); + entries.add(Diffs.createListDiffEntry(addIndex++, true, element)); } boolean added = wrappedList.addAll(index, c); fireListChange(Diffs.createListDiff(entries)); @@ -214,36 +217,40 @@ public class WritableList extends ObservableList { if (index == -1) { return false; } + + // Fetch it back so we can get it typed in a safe manner + E typedO = wrappedList.get(index); + wrappedList.remove(index); fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index, - false, o))); + false, typedO))); return true; } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { checkRealm(); - List entries = new ArrayList(); - for (Iterator it = c.iterator(); it.hasNext();) { + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>(); + for (Iterator<?> it = c.iterator(); it.hasNext();) { Object element = it.next(); int removeIndex = wrappedList.indexOf(element); if (removeIndex != -1) { + E removedElement = wrappedList.get(removeIndex); wrappedList.remove(removeIndex); entries.add(Diffs.createListDiffEntry(removeIndex, false, - element)); + removedElement)); } } if (entries.size() > 0) - fireListChange(Diffs.createListDiff((ListDiffEntry[]) entries - .toArray(new ListDiffEntry[entries.size()]))); + fireListChange(Diffs.createListDiff(entries)); return entries.size() > 0; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { checkRealm(); - List entries = new ArrayList(); + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>(); int removeIndex = 0; - for (Iterator it = wrappedList.iterator(); it.hasNext();) { - Object element = it.next(); + for (Iterator<E> it = wrappedList.iterator(); it.hasNext();) { + E element = it.next(); if (!c.contains(element)) { entries.add(Diffs.createListDiffEntry(removeIndex, false, element)); @@ -254,8 +261,7 @@ public class WritableList extends ObservableList { } } if (entries.size() > 0) - fireListChange(Diffs.createListDiff((ListDiffEntry[]) entries - .toArray(new ListDiffEntry[entries.size()]))); + fireListChange(Diffs.createListDiff(entries)); return entries.size() > 0; } @@ -263,14 +269,13 @@ public class WritableList extends ObservableList { checkRealm(); // We remove the elements from back to front which is typically much // faster on common list implementations like ArrayList. - ListDiffEntry[] entries = new ListDiffEntry[wrappedList.size()]; - int entryIndex = 0; - for (ListIterator it = wrappedList.listIterator(wrappedList.size()); it + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>( + wrappedList.size()); + for (ListIterator<E> it = wrappedList.listIterator(wrappedList.size()); it .hasPrevious();) { int elementIndex = it.previousIndex(); - Object element = it.previous(); - entries[entryIndex++] = Diffs.createListDiffEntry(elementIndex, - false, element); + E element = it.previous(); + entries.add(Diffs.createListDiffEntry(elementIndex, false, element)); } wrappedList.clear(); fireListChange(Diffs.createListDiff(entries)); @@ -281,8 +286,8 @@ public class WritableList extends ObservableList { * can be <code>null</code> * @return new list with the default realm. */ - public static WritableList withElementType(Object elementType) { - return new WritableList(Realm.getDefault(), new ArrayList(), - elementType); + public static WritableList<Object> withElementType(Object elementType) { + return new WritableList<Object>(Realm.getDefault(), + new ArrayList<Object>(), elementType); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java index 8d5e35a1..3e8c7542 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/AbstractObservableMap.java @@ -36,10 +36,14 @@ import org.eclipse.core.runtime.AssertionFailedException; * listeners may be invoked from any thread. * </p> * + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.0 */ -public abstract class AbstractObservableMap extends AbstractMap implements - IObservableMap { +public abstract class AbstractObservableMap<K, V> extends AbstractMap<K, V> + implements IObservableMap<K, V> { private final class PrivateChangeSupport extends ChangeSupport { private PrivateChangeSupport(Realm realm) { @@ -93,13 +97,15 @@ public abstract class AbstractObservableMap extends AbstractMap implements changeSupport = new PrivateChangeSupport(realm); } - public synchronized void addMapChangeListener(IMapChangeListener listener) { + public synchronized void addMapChangeListener( + IMapChangeListener<K, V> listener) { if (!disposed) { changeSupport.addListener(MapChangeEvent.TYPE, listener); } } - public synchronized void removeMapChangeListener(IMapChangeListener listener) { + public synchronized void removeMapChangeListener( + IMapChangeListener<K, V> listener) { if (!disposed) { changeSupport.removeListener(MapChangeEvent.TYPE, listener); } @@ -228,10 +234,10 @@ public abstract class AbstractObservableMap extends AbstractMap implements * * @param diff */ - protected void fireMapChange(MapDiff diff) { + protected void fireMapChange(MapDiff<K, V> diff) { checkRealm(); fireChange(); - changeSupport.fireEvent(new MapChangeEvent(this, diff)); + changeSupport.fireEvent(new MapChangeEvent<K, V>(this, diff)); } /** diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidiObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidiObservableMap.java index 600cd66a..9659fcfa 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidiObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidiObservableMap.java @@ -30,15 +30,26 @@ import org.eclipse.core.internal.databinding.observable.Util; * listeners may be invoked from any thread. * </p> * + * @param <K> + * @param <V> + * * @since 1.2 */ -public class BidiObservableMap extends DecoratingObservableMap { +public class BidiObservableMap<K, V> extends DecoratingObservableMap<K, V> { + /** + * Inverse of wrapped map. When only a single key map to a given value, it + * is put in this set. This field is null when no listeners are registered + * on this observable. + */ + private Map<V, K> valuesToSingleKeys = null; + /** * Inverse of wrapped map. When multiple keys map to the same value, they - * are combined into a Set. This field is null when no listeners are + * are combined into a Set, put in this map, and any single key in the + * single key map is removed. This field is null when no listeners are * registered on this observable. */ - private Map valuesToKeys; + private Map<V, Set<K>> valuesToSetsOfKeys = null; /** * Constructs a BidirectionalMap tracking the given observable map. @@ -46,14 +57,15 @@ public class BidiObservableMap extends DecoratingObservableMap { * @param wrappedMap * the observable map to track */ - public BidiObservableMap(IObservableMap wrappedMap) { + public BidiObservableMap(IObservableMap<K, V> wrappedMap) { super(wrappedMap, false); } protected void firstListenerAdded() { - valuesToKeys = new HashMap(); - for (Iterator it = entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Entry) it.next(); + valuesToSingleKeys = new HashMap<V, K>(); + valuesToSetsOfKeys = new HashMap<V, Set<K>>(); + for (Iterator<Entry<K, V>> it = entrySet().iterator(); it.hasNext();) { + Map.Entry<K, V> entry = it.next(); addMapping(entry.getKey(), entry.getValue()); } super.firstListenerAdded(); @@ -61,23 +73,25 @@ public class BidiObservableMap extends DecoratingObservableMap { protected void lastListenerRemoved() { super.lastListenerRemoved(); - valuesToKeys.clear(); - valuesToKeys = null; + valuesToSingleKeys.clear(); + valuesToSetsOfKeys.clear(); + valuesToSingleKeys = null; + valuesToSetsOfKeys = null; } - protected void handleMapChange(MapChangeEvent event) { - MapDiff diff = event.diff; - for (Iterator it = diff.getAddedKeys().iterator(); it.hasNext();) { - Object addedKey = it.next(); + protected void handleMapChange(MapChangeEvent<K, V> event) { + MapDiff<K, V> diff = event.diff; + for (Iterator<K> it = diff.getAddedKeys().iterator(); it.hasNext();) { + K addedKey = it.next(); addMapping(addedKey, diff.getNewValue(addedKey)); } - for (Iterator it = diff.getChangedKeys().iterator(); it.hasNext();) { - Object changedKey = it.next(); + for (Iterator<K> it = diff.getChangedKeys().iterator(); it.hasNext();) { + K changedKey = it.next(); removeMapping(changedKey, diff.getOldValue(changedKey)); addMapping(changedKey, diff.getNewValue(changedKey)); } - for (Iterator it = diff.getRemovedKeys().iterator(); it.hasNext();) { - Object removedKey = it.next(); + for (Iterator<K> it = diff.getRemovedKeys().iterator(); it.hasNext();) { + K removedKey = it.next(); removeMapping(removedKey, diff.getOldValue(removedKey)); } super.handleMapChange(event); @@ -86,8 +100,10 @@ public class BidiObservableMap extends DecoratingObservableMap { public boolean containsValue(Object value) { getterCalled(); // Faster lookup - if (valuesToKeys != null) - return valuesToKeys.containsKey(value); + if (valuesToSingleKeys != null) { + return (valuesToSingleKeys.containsKey(value) || valuesToSetsOfKeys + .containsKey(value)); + } return super.containsValue(value); } @@ -95,25 +111,24 @@ public class BidiObservableMap extends DecoratingObservableMap { * Adds a mapping from value to key in the valuesToKeys map. * * @param key - * the key being mapped + * the key being mapped, which may be the key itself or it may be + * a set of keys * @param value * the value being mapped */ - private void addMapping(Object key, Object value) { - if (!valuesToKeys.containsKey(value)) { - if (key instanceof Set) - key = new HashSet(Collections.singleton(key)); - valuesToKeys.put(value, key); - } else { - Object elementOrSet = valuesToKeys.get(value); - Set set; - if (elementOrSet instanceof Set) { - set = (Set) elementOrSet; - } else { - set = new HashSet(Collections.singleton(elementOrSet)); - valuesToKeys.put(value, set); - } + private void addMapping(K key, V value) { + if (valuesToSingleKeys.containsKey(value)) { + K element = valuesToSingleKeys.get(value); + Set<K> set; + set = new HashSet<K>(Collections.singleton(element)); + valuesToSingleKeys.remove(value); + valuesToSetsOfKeys.put(value, set); set.add(key); + } else if (valuesToSetsOfKeys.containsKey(value)) { + Set<K> keySet = valuesToSetsOfKeys.get(value); + keySet.add(key); + } else { + valuesToSingleKeys.put(value, key); } } @@ -125,18 +140,17 @@ public class BidiObservableMap extends DecoratingObservableMap { * @param value * the value being unmapped */ - private void removeMapping(Object key, Object value) { - if (valuesToKeys.containsKey(value)) { - Object elementOrSet = valuesToKeys.get(value); - if (elementOrSet instanceof Set) { - Set set = (Set) elementOrSet; - set.remove(key); - if (set.isEmpty()) { - valuesToKeys.remove(value); - } - } else if (elementOrSet == key - || (elementOrSet != null && elementOrSet.equals(key))) { - valuesToKeys.remove(value); + private void removeMapping(Object key, V value) { + if (valuesToSingleKeys.containsKey(value)) { + K element = valuesToSingleKeys.get(value); + if (element == key || (element != null && element.equals(key))) { + valuesToSingleKeys.remove(value); + } + } else if (valuesToSetsOfKeys.containsKey(value)) { + Set<K> keySet = valuesToSetsOfKeys.get(value); + keySet.remove(key); + if (keySet.isEmpty()) { + valuesToSetsOfKeys.remove(value); } } } @@ -149,17 +163,18 @@ public class BidiObservableMap extends DecoratingObservableMap { * @return the Set of keys that map to the given value. If no keys map to * the given value, an empty set is returned. */ - public Set getKeys(Object value) { - // valuesToKeys is null when no listeners are registered - if (valuesToKeys == null) + public Set<K> getKeys(Object value) { + // valuesToSingleKeys is null when no listeners are registered + if (valuesToSingleKeys == null) return findKeys(value); - if (!valuesToKeys.containsKey(value)) - return Collections.EMPTY_SET; - Object elementOrSet = valuesToKeys.get(value); - if (elementOrSet instanceof Set) - return Collections.unmodifiableSet((Set) elementOrSet); - return Collections.singleton(elementOrSet); + if (valuesToSingleKeys.containsKey(value)) { + return Collections.singleton(valuesToSingleKeys.get(value)); + } else if (valuesToSetsOfKeys.containsKey(value)) { + return Collections.unmodifiableSet(valuesToSetsOfKeys.get(value)); + } else { + return Collections.emptySet(); + } } /** @@ -170,10 +185,10 @@ public class BidiObservableMap extends DecoratingObservableMap { * the value to search for * @return the set of keys which currently map to the specified value. */ - private Set findKeys(Object value) { - Set keys = new HashSet(); - for (Iterator it = entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); + private Set<K> findKeys(Object value) { + Set<K> keys = new HashSet<K>(); + for (Iterator<Entry<K, V>> it = entrySet().iterator(); it.hasNext();) { + Map.Entry<K, V> entry = it.next(); if (Util.equals(entry.getValue(), value)) keys.add(entry.getKey()); } @@ -181,9 +196,13 @@ public class BidiObservableMap extends DecoratingObservableMap { } public synchronized void dispose() { - if (valuesToKeys != null) { - valuesToKeys.clear(); - valuesToKeys = null; + if (valuesToSingleKeys != null) { + valuesToSingleKeys.clear(); + valuesToSingleKeys = null; + } + if (valuesToSetsOfKeys != null) { + valuesToSetsOfKeys.clear(); + valuesToSetsOfKeys = null; } super.dispose(); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidirectionalMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidirectionalMap.java index 788086bc..49810148 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidirectionalMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/BidirectionalMap.java @@ -20,13 +20,21 @@ import org.eclipse.core.databinding.observable.Realm; * the {@link Realm#isCurrent() current realm}. Methods for adding and removing * listeners may be invoked from any thread. * </p> + * * @since 1.0 * + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map + * * @deprecated This class is deprecated; use {@link BidiObservableMap} instead. */ -public class BidirectionalMap extends ObservableMap { - private IMapChangeListener mapListener = new IMapChangeListener() { - public void handleMapChange(MapChangeEvent event) { +@SuppressWarnings({ "rawtypes", "unchecked" }) +// OK to ignore warnings in deprecated class +public class BidirectionalMap<K, V> extends ObservableMap { + private IMapChangeListener mapListener = new IMapChangeListener<K, V>() { + public void handleMapChange(MapChangeEvent<K, V> event) { fireMapChange(event.diff); } }; diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/CompositeMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/CompositeMap.java index 31bc661a..e71a2320 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/CompositeMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/CompositeMap.java @@ -38,37 +38,43 @@ import org.eclipse.core.runtime.Assert; * listeners may be invoked from any thread. * </p> * + * @param <K> + * @param <I> + * the type of the intermediate values + * @param <V> + * * @since 1.1 * */ -public class CompositeMap extends ObservableMap { +public class CompositeMap<K, I, V> extends ObservableMap<K, V> { // adds that need to go through the second map and thus will be picked up by // secondMapListener. - private Set pendingAdds = new HashSet(); + private Set<I> pendingAdds = new HashSet<I>(); // Removes that need to go through the second map and thus will be picked up // by secondMapListener. Maps from value being removed to key being removed. - private Map pendingRemoves = new HashMap(); + private Map<I, K> pendingRemoves = new HashMap<I, K>(); // Changes that need to go through the second map and thus will be picked up - // by secondMapListener. Maps from old value to new value and new value to old + // by secondMapListener. Maps from old value to new value and new value to + // old // value. - private Map pendingChanges = new HashMap(); - - private IMapChangeListener firstMapListener = new IMapChangeListener() { - - public void handleMapChange(MapChangeEvent event) { - MapDiff diff = event.diff; - Set rangeSetAdditions = new HashSet(); - Set rangeSetRemovals = new HashSet(); - final Set adds = new HashSet(); - final Set changes = new HashSet(); - final Set removes = new HashSet(); - final Map oldValues = new HashMap(); - - for (Iterator it = diff.getAddedKeys().iterator(); it.hasNext();) { - Object addedKey = it.next(); - Object newValue = diff.getNewValue(addedKey); + private Map<I, I> pendingChanges = new HashMap<I, I>(); + + private IMapChangeListener<K, I> firstMapListener = new IMapChangeListener<K, I>() { + + public void handleMapChange(MapChangeEvent<K, I> event) { + MapDiff<K, I> diff = event.diff; + Set<I> rangeSetAdditions = new HashSet<I>(); + Set<I> rangeSetRemovals = new HashSet<I>(); + final Set<K> adds = new HashSet<K>(); + final Set<K> changes = new HashSet<K>(); + final Set<K> removes = new HashSet<K>(); + final Map<K, V> oldValues = new HashMap<K, V>(); + + for (Iterator<K> it = diff.getAddedKeys().iterator(); it.hasNext();) { + K addedKey = it.next(); + I newValue = diff.getNewValue(addedKey); if (!rangeSet.contains(newValue)) { pendingAdds.add(newValue); rangeSetAdditions.add(newValue); @@ -77,10 +83,11 @@ public class CompositeMap extends ObservableMap { wrappedMap.put(addedKey, secondMap.get(newValue)); } } - for (Iterator it = diff.getChangedKeys().iterator(); it.hasNext();) { - Object changedKey = it.next(); - Object oldValue = diff.getOldValue(changedKey); - Object newValue = diff.getNewValue(changedKey); + for (Iterator<K> it = diff.getChangedKeys().iterator(); it + .hasNext();) { + K changedKey = it.next(); + I oldValue = diff.getOldValue(changedKey); + I newValue = diff.getNewValue(changedKey); boolean removed = firstMap.getKeys(oldValue).isEmpty(); boolean added = !rangeSet.contains(newValue); if (removed) { @@ -96,13 +103,14 @@ public class CompositeMap extends ObservableMap { pendingChanges.put(newValue, oldValue); } else { changes.add(changedKey); - oldValues.put(changedKey, oldValue); + oldValues.put(changedKey, secondMap.get(oldValue)); wrappedMap.put(changedKey, secondMap.get(newValue)); } } - for (Iterator it = diff.getRemovedKeys().iterator(); it.hasNext();) { - Object removedKey = it.next(); - Object oldValue = diff.getOldValue(removedKey); + for (Iterator<K> it = diff.getRemovedKeys().iterator(); it + .hasNext();) { + K removedKey = it.next(); + I oldValue = diff.getOldValue(removedKey); if (firstMap.getKeys(oldValue).isEmpty()) { pendingRemoves.put(oldValue, removedKey); rangeSetRemovals.add(oldValue); @@ -114,25 +122,25 @@ public class CompositeMap extends ObservableMap { } if (adds.size() > 0 || removes.size() > 0 || changes.size() > 0) { - fireMapChange(new MapDiff() { + fireMapChange(new MapDiff<K, V>() { - public Set getAddedKeys() { + public Set<K> getAddedKeys() { return adds; } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return changes; } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return wrappedMap.get(key); } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValues.get(key); } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return removes; } }); @@ -144,25 +152,25 @@ public class CompositeMap extends ObservableMap { } }; - private IMapChangeListener secondMapListener = new IMapChangeListener() { - - public void handleMapChange(MapChangeEvent event) { - MapDiff diff = event.diff; - final Set adds = new HashSet(); - final Set changes = new HashSet(); - final Set removes = new HashSet(); - final Map oldValues = new HashMap(); - final Map newValues = new HashMap(); - Set addedKeys = new HashSet(diff.getAddedKeys()); - Set removedKeys = new HashSet(diff.getRemovedKeys()); - - for (Iterator it = addedKeys.iterator(); it.hasNext();) { - Object addedKey = it.next(); - Set elements = firstMap.getKeys(addedKey); - Object newValue = diff.getNewValue(addedKey); + private IMapChangeListener<I, V> secondMapListener = new IMapChangeListener<I, V>() { + + public void handleMapChange(MapChangeEvent<I, V> event) { + MapDiff<I, V> diff = event.diff; + final Set<K> adds = new HashSet<K>(); + final Set<K> changes = new HashSet<K>(); + final Set<K> removes = new HashSet<K>(); + final Map<K, V> oldValues = new HashMap<K, V>(); + final Map<K, V> newValues = new HashMap<K, V>(); + Set<I> addedKeys = new HashSet<I>(diff.getAddedKeys()); + Set<I> removedKeys = new HashSet<I>(diff.getRemovedKeys()); + + for (Iterator<I> it = addedKeys.iterator(); it.hasNext();) { + I addedKey = it.next(); + Set<K> elements = firstMap.getKeys(addedKey); + V newValue = diff.getNewValue(addedKey); if (pendingChanges.containsKey(addedKey)) { - Object oldKey = pendingChanges.remove(addedKey); - Object oldValue; + I oldKey = pendingChanges.remove(addedKey); + V oldValue; if (removedKeys.remove(oldKey)) { oldValue = diff.getOldValue(oldKey); } else { @@ -171,16 +179,16 @@ public class CompositeMap extends ObservableMap { pendingChanges.remove(oldKey); pendingAdds.remove(addedKey); pendingRemoves.remove(oldKey); - for (Iterator it2 = elements.iterator(); it2.hasNext();) { - Object element = it2.next(); + for (Iterator<K> it2 = elements.iterator(); it2.hasNext();) { + K element = it2.next(); changes.add(element); oldValues.put(element, oldValue); newValues.put(element, newValue); wrappedMap.put(element, newValue); } } else if (pendingAdds.remove(addedKey)) { - for (Iterator it2 = elements.iterator(); it2.hasNext();) { - Object element = it2.next(); + for (Iterator<K> it2 = elements.iterator(); it2.hasNext();) { + K element = it2.next(); adds.add(element); newValues.put(element, newValue); wrappedMap.put(element, newValue); @@ -189,21 +197,22 @@ public class CompositeMap extends ObservableMap { Assert.isTrue(false, "unexpected case"); //$NON-NLS-1$ } } - for (Iterator it = diff.getChangedKeys().iterator(); it.hasNext();) { - Object changedKey = it.next(); - Set elements = firstMap.getKeys(changedKey); - for (Iterator it2 = elements.iterator(); it2.hasNext();) { - Object element = it2.next(); + for (Iterator<I> it = diff.getChangedKeys().iterator(); it + .hasNext();) { + I changedKey = it.next(); + Set<K> elements = firstMap.getKeys(changedKey); + for (Iterator<K> it2 = elements.iterator(); it2.hasNext();) { + K element = it2.next(); changes.add(element); oldValues.put(element, diff.getOldValue(changedKey)); - Object newValue = diff.getNewValue(changedKey); + V newValue = diff.getNewValue(changedKey); newValues.put(element, newValue); wrappedMap.put(element, newValue); } } - for (Iterator it = removedKeys.iterator(); it.hasNext();) { - Object removedKey = it.next(); - Object element = pendingRemoves.remove(removedKey); + for (Iterator<I> it = removedKeys.iterator(); it.hasNext();) { + I removedKey = it.next(); + K element = pendingRemoves.remove(removedKey); if (element != null) { if (pendingChanges.containsKey(removedKey)) { Object newKey = pendingChanges.remove(removedKey); @@ -212,12 +221,12 @@ public class CompositeMap extends ObservableMap { pendingRemoves.remove(removedKey); changes.add(element); oldValues.put(element, diff.getOldValue(removedKey)); - Object newValue = secondMap.get(newKey); + V newValue = secondMap.get(newKey); newValues.put(element, newValue); wrappedMap.put(element, newValue); } else { removes.add(element); - Object oldValue = diff.getOldValue(removedKey); + V oldValue = diff.getOldValue(removedKey); oldValues.put(element, oldValue); wrappedMap.remove(element); } @@ -227,25 +236,25 @@ public class CompositeMap extends ObservableMap { } if (adds.size() > 0 || removes.size() > 0 || changes.size() > 0) { - fireMapChange(new MapDiff() { + fireMapChange(new MapDiff<K, V>() { - public Set getAddedKeys() { + public Set<K> getAddedKeys() { return adds; } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return changes; } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return newValues.get(key); } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValues.get(key); } - public Set getRemovedKeys() { + public Set<K> getRemovedKeys() { return removes; } }); @@ -253,18 +262,18 @@ public class CompositeMap extends ObservableMap { } }; - private BidiObservableMap firstMap; - private IObservableMap secondMap; + private BidiObservableMap<K, I> firstMap; + private IObservableMap<I, V> secondMap; - private static class WritableSetPlus extends WritableSet { - void addAndRemove(Set additions, Set removals) { + private static class WritableSetPlus<E> extends WritableSet<E> { + void addAndRemove(Set<E> additions, Set<E> removals) { wrappedSet.removeAll(removals); wrappedSet.addAll(additions); fireSetChange(Diffs.createSetDiff(additions, removals)); } } - private WritableSetPlus rangeSet = new WritableSetPlus(); + private WritableSetPlus<I> rangeSet = new WritableSetPlus<I>(); /** * Creates a new composite map. Because the key set of the second map is @@ -279,17 +288,17 @@ public class CompositeMap extends ObservableMap { * a factory that creates the second map when given an observable * set representing the value set of <code>firstMap</code>. */ - public CompositeMap(IObservableMap firstMap, - IObservableFactory secondMapFactory) { - super(firstMap.getRealm(), new HashMap()); - this.firstMap = new BidiObservableMap(firstMap); + public CompositeMap(IObservableMap<K, I> firstMap, + IObservableFactory<Set<I>, IObservableMap<I, V>> secondMapFactory) { + super(firstMap.getRealm(), new HashMap<K, V>()); + this.firstMap = new BidiObservableMap<K, I>(firstMap); this.firstMap.addMapChangeListener(firstMapListener); rangeSet.addAll(this.firstMap.values()); - this.secondMap = (IObservableMap) secondMapFactory - .createObservable(rangeSet); + this.secondMap = secondMapFactory.createObservable(rangeSet); secondMap.addMapChangeListener(secondMapListener); - for (Iterator it = this.firstMap.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Entry) it.next(); + for (Iterator<Map.Entry<K, I>> it = this.firstMap.entrySet().iterator(); it + .hasNext();) { + Map.Entry<K, I> entry = it.next(); wrappedMap.put(entry.getKey(), secondMap.get(entry.getValue())); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ComputedObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ComputedObservableMap.java index 60aaadd4..9497a870 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ComputedObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ComputedObservableMap.java @@ -36,24 +36,30 @@ import org.eclipse.core.internal.databinding.identity.IdentitySet; /** * Maps objects to one of their attributes. Tracks changes to the underlying * observable set of objects (keys), as well as changes to attribute values. + * + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map */ -public abstract class ComputedObservableMap extends AbstractObservableMap { +public abstract class ComputedObservableMap<K, V> extends + AbstractObservableMap<K, V> { - private IObservableSet keySet; + private IObservableSet<K> keySet; - private Set knownKeys; + private Set<K> knownKeys; private Object valueType; - private ISetChangeListener setChangeListener = new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { - Set addedKeys = new HashSet(event.diff.getAdditions()); - Set removedKeys = new HashSet(event.diff.getRemovals()); - Map oldValues = new HashMap(); - Map newValues = new HashMap(); - for (Iterator it = removedKeys.iterator(); it.hasNext();) { - Object removedKey = it.next(); - Object oldValue = null; + private ISetChangeListener<K> setChangeListener = new ISetChangeListener<K>() { + public void handleSetChange(SetChangeEvent<K> event) { + Set<K> addedKeys = new HashSet<K>(event.diff.getAdditions()); + Set<K> removedKeys = new HashSet<K>(event.diff.getRemovals()); + Map<K, V> oldValues = new HashMap<K, V>(); + Map<K, V> newValues = new HashMap<K, V>(); + for (Iterator<K> it = removedKeys.iterator(); it.hasNext();) { + K removedKey = it.next(); + V oldValue = null; if (removedKey != null) { oldValue = doGet(removedKey); unhookListener(removedKey); @@ -61,9 +67,9 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { } oldValues.put(removedKey, oldValue); } - for (Iterator it = addedKeys.iterator(); it.hasNext();) { - Object addedKey = it.next(); - Object newValue = null; + for (Iterator<K> it = addedKeys.iterator(); it.hasNext();) { + K addedKey = it.next(); + V newValue = null; if (addedKey != null) { newValue = doGet(addedKey); hookListener(addedKey); @@ -71,8 +77,9 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { } newValues.put(addedKey, newValue); } + Set<K> changedKeys = Collections.emptySet(); fireMapChange(Diffs.createMapDiff(addedKeys, removedKeys, - Collections.EMPTY_SET, oldValues, newValues)); + changedKeys, oldValues, newValues)); } }; @@ -82,32 +89,32 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { } }; - private Set entrySet = new EntrySet(); + private Set<Map.Entry<K, V>> entrySet = new EntrySet(); - private class EntrySet extends AbstractSet { + private class EntrySet extends AbstractSet<Map.Entry<K, V>> { - public Iterator iterator() { - final Iterator keyIterator = keySet.iterator(); - return new Iterator() { + public Iterator<Map.Entry<K, V>> iterator() { + final Iterator<K> keyIterator = keySet.iterator(); + return new Iterator<Map.Entry<K, V>>() { public boolean hasNext() { return keyIterator.hasNext(); } - public Object next() { - final Object key = keyIterator.next(); - return new Map.Entry() { + public Map.Entry<K, V> next() { + final K key = keyIterator.next(); + return new Map.Entry<K, V>() { - public Object getKey() { + public K getKey() { getterCalled(); return key; } - public Object getValue() { + public V getValue() { return get(getKey()); } - public Object setValue(Object value) { + public V setValue(V value) { return put(getKey(), value); } }; @@ -128,7 +135,7 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { /** * @param keySet */ - public ComputedObservableMap(IObservableSet keySet) { + public ComputedObservableMap(IObservableSet<K> keySet) { this(keySet, null); } @@ -137,13 +144,13 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { * @param valueType * @since 1.2 */ - public ComputedObservableMap(IObservableSet keySet, Object valueType) { + public ComputedObservableMap(IObservableSet<K> keySet, Object valueType) { super(keySet.getRealm()); this.keySet = keySet; this.valueType = valueType; keySet.addDisposeListener(new IDisposeListener() { - public void handleDispose(DisposeEvent staleEvent) { + public void handleDispose(DisposeEvent disposeEvent) { ComputedObservableMap.this.dispose(); } }); @@ -169,11 +176,11 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { private void hookListeners() { if (keySet != null) { - knownKeys = new IdentitySet(); + knownKeys = new IdentitySet<K>(); keySet.addSetChangeListener(setChangeListener); keySet.addStaleListener(staleListener); - for (Iterator it = this.keySet.iterator(); it.hasNext();) { - Object key = it.next(); + for (Iterator<K> it = this.keySet.iterator(); it.hasNext();) { + K key = it.next(); hookListener(key); knownKeys.add(key); } @@ -186,17 +193,16 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { keySet.removeStaleListener(staleListener); } if (knownKeys != null) { - Object[] keys = knownKeys.toArray(); - for (int i = 0; i < keys.length; i++) { - unhookListener(keys[i]); + Set<K> immutableKnownKeys = Collections.unmodifiableSet(knownKeys); + for (K key : immutableKnownKeys) { + unhookListener(key); } knownKeys.clear(); knownKeys = null; } } - protected final void fireSingleChange(Object key, Object oldValue, - Object newValue) { + protected final void fireSingleChange(K key, V oldValue, V newValue) { fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue, newValue)); } @@ -217,10 +223,10 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { /** * @since 1.3 */ - public Object remove(Object key) { + public V remove(Object key) { checkRealm(); - Object oldValue = get(key); + V oldValue = get(key); keySet().remove(key); return oldValue; @@ -234,26 +240,26 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { return keySet().contains(key); } - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { return entrySet; } - public Set keySet() { + public Set<K> keySet() { return keySet; } - final public Object get(Object key) { + final public V get(Object key) { getterCalled(); if (!keySet.contains(key)) return null; - return doGet(key); + return doGet((K) key); } private void getterCalled() { ObservableTracker.getterCalled(this); } - final public Object put(Object key, Object value) { + final public V put(K key, V value) { checkRealm(); if (!keySet.contains(key)) return null; @@ -263,25 +269,25 @@ public abstract class ComputedObservableMap extends AbstractObservableMap { /** * @param removedKey */ - protected abstract void unhookListener(Object removedKey); + protected abstract void unhookListener(K removedKey); /** * @param addedKey */ - protected abstract void hookListener(Object addedKey); + protected abstract void hookListener(K addedKey); /** * @param key * @return the value for the given key */ - protected abstract Object doGet(Object key); + protected abstract V doGet(K key); /** * @param key * @param value * @return the old value for the given key */ - protected abstract Object doPut(Object key, Object value); + protected abstract V doPut(K key, V value); public boolean isStale() { return super.isStale() || keySet.isStale(); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/DecoratingObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/DecoratingObservableMap.java index c0a1bb7a..3ef70ea4 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/DecoratingObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/DecoratingObservableMap.java @@ -22,13 +22,16 @@ import org.eclipse.core.databinding.observable.DecoratingObservable; /** * An observable map which decorates another observable map. * + * @param <K> + * @param <V> + * * @since 1.2 */ -public class DecoratingObservableMap extends DecoratingObservable implements - IObservableMap { - private IObservableMap decorated; +public class DecoratingObservableMap<K, V> extends DecoratingObservable + implements IObservableMap<K, V> { + private IObservableMap<K, V> decorated; - private IMapChangeListener mapChangeListener; + private IMapChangeListener<K, V> mapChangeListener; /** * Constructs a DecoratingObservableMap which decorates the given @@ -38,17 +41,19 @@ public class DecoratingObservableMap extends DecoratingObservable implements * the observable map being decorated * @param disposeDecoratedOnDispose */ - public DecoratingObservableMap(IObservableMap decorated, + public DecoratingObservableMap(IObservableMap<K, V> decorated, boolean disposeDecoratedOnDispose) { super(decorated, disposeDecoratedOnDispose); this.decorated = decorated; } - public synchronized void addMapChangeListener(IMapChangeListener listener) { + public synchronized void addMapChangeListener( + IMapChangeListener<K, V> listener) { addListener(MapChangeEvent.TYPE, listener); } - public synchronized void removeMapChangeListener(IMapChangeListener listener) { + public synchronized void removeMapChangeListener( + IMapChangeListener<K, V> listener) { removeListener(MapChangeEvent.TYPE, listener); } @@ -60,10 +65,10 @@ public class DecoratingObservableMap extends DecoratingObservable implements return decorated.getValueType(); } - protected void fireMapChange(MapDiff diff) { + protected void fireMapChange(MapDiff<K, V> diff) { // fire general change event first super.fireChange(); - fireEvent(new MapChangeEvent(this, diff)); + fireEvent(new MapChangeEvent<K, V>(this, diff)); } protected void fireChange() { @@ -73,8 +78,8 @@ public class DecoratingObservableMap extends DecoratingObservable implements protected void firstListenerAdded() { if (mapChangeListener == null) { - mapChangeListener = new IMapChangeListener() { - public void handleMapChange(MapChangeEvent event) { + mapChangeListener = new IMapChangeListener<K, V>() { + public void handleMapChange(MapChangeEvent<K, V> event) { DecoratingObservableMap.this.handleMapChange(event); } }; @@ -100,7 +105,7 @@ public class DecoratingObservableMap extends DecoratingObservable implements * @param event * the change event received from the decorated observable */ - protected void handleMapChange(final MapChangeEvent event) { + protected void handleMapChange(final MapChangeEvent<K, V> event) { fireMapChange(event.diff); } @@ -119,18 +124,18 @@ public class DecoratingObservableMap extends DecoratingObservable implements return decorated.containsValue(value); } - private class BackedCollection implements Collection { - private Collection collection; + private class BackedCollection<E> implements Collection<E> { + private Collection<E> collection; - BackedCollection(Collection set) { + BackedCollection(Collection<E> set) { this.collection = set; } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection arg0) { + public boolean addAll(Collection<? extends E> arg0) { throw new UnsupportedOperationException(); } @@ -144,7 +149,7 @@ public class DecoratingObservableMap extends DecoratingObservable implements return collection.contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return collection.containsAll(c); } @@ -154,15 +159,15 @@ public class DecoratingObservableMap extends DecoratingObservable implements return collection.isEmpty(); } - public Iterator iterator() { - final Iterator iterator = collection.iterator(); - return new Iterator() { + public Iterator<E> iterator() { + final Iterator<E> iterator = collection.iterator(); + return new Iterator<E>() { public boolean hasNext() { getterCalled(); return iterator.hasNext(); } - public Object next() { + public E next() { getterCalled(); return iterator.next(); } @@ -179,12 +184,12 @@ public class DecoratingObservableMap extends DecoratingObservable implements return collection.remove(o); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { getterCalled(); return collection.removeAll(c); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { getterCalled(); return collection.retainAll(c); } @@ -199,7 +204,7 @@ public class DecoratingObservableMap extends DecoratingObservable implements return collection.toArray(); } - public Object[] toArray(Object[] array) { + public <T> T[] toArray(T[] array) { getterCalled(); return collection.toArray(array); } @@ -220,23 +225,23 @@ public class DecoratingObservableMap extends DecoratingObservable implements } } - private class BackedSet extends BackedCollection implements Set { - BackedSet(Set set) { + private class BackedSet<E> extends BackedCollection<E> implements Set<E> { + BackedSet(Set<E> set) { super(set); } } - Set entrySet = null; + Set<Entry<K, V>> entrySet = null; - public Set entrySet() { + public Set<Entry<K, V>> entrySet() { getterCalled(); if (entrySet == null) { - entrySet = new BackedSet(decorated.entrySet()); + entrySet = new BackedSet<Entry<K, V>>(decorated.entrySet()); } return entrySet; } - public Object get(Object key) { + public V get(Object key) { getterCalled(); return decorated.get(key); } @@ -246,27 +251,27 @@ public class DecoratingObservableMap extends DecoratingObservable implements return decorated.isEmpty(); } - Set keySet = null; + Set<K> keySet = null; - public Set keySet() { + public Set<K> keySet() { getterCalled(); if (keySet == null) { - keySet = new BackedSet(decorated.keySet()); + keySet = new BackedSet<K>(decorated.keySet()); } return keySet; } - public Object put(Object key, Object value) { + public V put(K key, V value) { checkRealm(); return decorated.put(key, value); } - public void putAll(Map m) { + public void putAll(Map<? extends K, ? extends V> m) { checkRealm(); decorated.putAll(m); } - public Object remove(Object key) { + public V remove(Object key) { checkRealm(); return decorated.remove(key); } @@ -276,12 +281,12 @@ public class DecoratingObservableMap extends DecoratingObservable implements return decorated.size(); } - Collection values; + Collection<V> values; - public Collection values() { + public Collection<V> values() { getterCalled(); if (values == null) { - values = new BackedCollection(decorated.values()); + values = new BackedCollection<V>(decorated.values()); } return values; } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IMapChangeListener.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IMapChangeListener.java index 3bc829e9..9d86c9e8 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IMapChangeListener.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IMapChangeListener.java @@ -16,10 +16,14 @@ import org.eclipse.core.databinding.observable.IObservablesListener; /** * Listener for changes to observable maps. * + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.0 * */ -public interface IMapChangeListener extends IObservablesListener { +public interface IMapChangeListener<K, V> extends IObservablesListener { /** * Handle a change an observable map. The given event object must only be @@ -30,6 +34,6 @@ public interface IMapChangeListener extends IObservablesListener { * @param event * the event */ - void handleMapChange(MapChangeEvent event); + void handleMapChange(MapChangeEvent<K, V> event); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IObservableMap.java index 20c01384..36b2c0d8 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/IObservableMap.java @@ -22,19 +22,22 @@ import org.eclipse.core.databinding.observable.IObservable; /** * Observable Map. * + * @param <K> + * @param <V> + * * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that * implement this interface. Note that direct implementers of this * interface outside of the framework will be broken in future * releases when methods are added to this interface. - * + * * @see AbstractObservableMap * @see ObservableMap * * @since 1.1 */ -public interface IObservableMap extends Map, IObservable { - +public interface IObservableMap<K, V> extends Map<K, V>, IObservable { + /** * Returns the element type for the {@link #keySet() keyset} of this * observable map, or <code>null</code> if the keyset is untyped. @@ -59,13 +62,13 @@ public interface IObservableMap extends Map, IObservable { /** * @param listener */ - public void addMapChangeListener(IMapChangeListener listener); + public void addMapChangeListener(IMapChangeListener<K, V> listener); /** * @param listener */ - public void removeMapChangeListener(IMapChangeListener listener); - + public void removeMapChangeListener(IMapChangeListener<K, V> listener); + /** * @TrackedGetter */ @@ -89,32 +92,32 @@ public interface IObservableMap extends Map, IObservable { /** * @TrackedGetter */ - public Object get(Object key); + public V get(Object key); /** * */ - public Object put(Object key, Object value); + public V put(K key, V value); /** * */ - public Object remove(Object key); + public V remove(Object key); /** * @TrackedGetter */ - public Set keySet(); + public Set<K> keySet(); /** * @TrackedGetter */ - public Collection values(); + public Collection<V> values(); /** * @TrackedGetter */ - public Set entrySet(); + public Set<Map.Entry<K, V>> entrySet(); /** * @TrackedGetter diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapChangeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapChangeEvent.java index 90bfef93..882b332f 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapChangeEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapChangeEvent.java @@ -18,10 +18,14 @@ import org.eclipse.core.databinding.observable.ObservableEvent; * Map change event describing an incremental change of an * {@link IObservableMap} object. * + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.0 * */ -public class MapChangeEvent extends ObservableEvent { +public class MapChangeEvent<K, V> extends ObservableEvent<MapChangeEvent<K, V>> { /** * @@ -33,7 +37,13 @@ public class MapChangeEvent extends ObservableEvent { * Description of the change to the source observable map. Listeners must * not change this field. */ - public MapDiff diff; + public MapDiff<K, V> diff; + + /** + * Always identical to <code>EventObject.source</code> but the type + * information is maintained. + */ + private IObservableMap<K, V> typedSource; /** * Creates a new map change event @@ -43,8 +53,9 @@ public class MapChangeEvent extends ObservableEvent { * @param diff * the map change */ - public MapChangeEvent(IObservableMap source, MapDiff diff) { + public MapChangeEvent(IObservableMap<K, V> source, MapDiff<K, V> diff) { super(source); + this.typedSource = source; this.diff = diff; } @@ -53,12 +64,12 @@ public class MapChangeEvent extends ObservableEvent { * * @return the observable map from which this event originated */ - public IObservableMap getObservableMap() { - return (IObservableMap) getSource(); + public IObservableMap<K, V> getObservableMap() { + return typedSource; } protected void dispatch(IObservablesListener listener) { - ((IMapChangeListener) listener).handleMapChange(this); + ((IMapChangeListener<K, V>) listener).handleMapChange(this); } protected Object getListenerType() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapDiff.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapDiff.java index d710c132..adb2deb0 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapDiff.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/MapDiff.java @@ -16,18 +16,22 @@ import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.Set; -import java.util.Map.Entry; import org.eclipse.core.databinding.observable.IDiff; import org.eclipse.core.internal.databinding.observable.Util; /** + * @param <K> + * the type of keys maintained by this map + * @param <V> + * the type of mapped values * @since 1.1 * */ -public abstract class MapDiff implements IDiff { +public abstract class MapDiff<K, V> implements IDiff { /** * Returns true if the diff has no added, removed or changed entries. * @@ -46,16 +50,16 @@ public abstract class MapDiff implements IDiff { * the map to which the diff will be applied * @since 1.2 */ - public void applyTo(Map map) { - for (Iterator it = getAddedKeys().iterator(); it.hasNext();) { - Object key = it.next(); + public void applyTo(Map<K, V> map) { + for (Iterator<K> it = getAddedKeys().iterator(); it.hasNext();) { + K key = it.next(); map.put(key, getNewValue(key)); } - for (Iterator it = getChangedKeys().iterator(); it.hasNext();) { - Object key = it.next(); + for (Iterator<K> it = getChangedKeys().iterator(); it.hasNext();) { + K key = it.next(); map.put(key, getNewValue(key)); } - for (Iterator it = getRemovedKeys().iterator(); it.hasNext();) { + for (Iterator<K> it = getRemovedKeys().iterator(); it.hasNext();) { map.remove(it.next()); } } @@ -74,18 +78,18 @@ public abstract class MapDiff implements IDiff { * @see #applyTo(Map) * @since 1.3 */ - public Map simulateOn(Map map) { - return new DeltaMap(map, this); + public Map<K, V> simulateOn(Map<K, V> map) { + return new DeltaMap<K, V>(map, this); } - private static class DeltaMap extends AbstractMap { + private static class DeltaMap<K, V> extends AbstractMap<K, V> { - private final Map map; - private final MapDiff diff; + private final Map<K, V> map; + private final MapDiff<K, V> diff; - private Set entrySet; + private Set<Entry<K, V>> entrySet; - public DeltaMap(Map map, MapDiff diff) { + public DeltaMap(Map<K, V> map, MapDiff<K, V> diff) { this.map = map; this.diff = diff; @@ -101,14 +105,14 @@ public abstract class MapDiff implements IDiff { .contains(key)); } - public Set entrySet() { + public Set<Entry<K, V>> entrySet() { if (entrySet == null) { - entrySet = new DeltaMapEntrySet(map, diff); + entrySet = new DeltaMapEntrySet<K, V>(map, diff); } return entrySet; } - public Object get(Object key) { + public V get(Object key) { if (diff.getAddedKeys().contains(key)) return diff.getNewValue(key); if (diff.getChangedKeys().contains(key)) @@ -118,47 +122,49 @@ public abstract class MapDiff implements IDiff { return map.get(key); } - public Object put(Object arg0, Object arg1) { + public V put(Object arg0, Object arg1) { throw new UnsupportedOperationException(); } - public void putAll(Map arg0) { + public void putAll(Map<? extends K, ? extends V> arg0) { throw new UnsupportedOperationException(); } - public Object remove(Object key) { + public V remove(Object key) { throw new UnsupportedOperationException(); } } - private static class DeltaMapEntrySet extends AbstractSet { + private static class DeltaMapEntrySet<K, V> extends + AbstractSet<Map.Entry<K, V>> { - private final Map map; - private final MapDiff diff; + private final Map<K, V> map; + private final MapDiff<K, V> diff; - public DeltaMapEntrySet(Map map, MapDiff diff) { + public DeltaMapEntrySet(Map<K, V> map, MapDiff<K, V> diff) { this.map = map; this.diff = diff; } - public Iterator iterator() { - return new Iterator() { - Iterator origEntries = map.entrySet().iterator(); - Iterator addedKeys = diff.getAddedKeys().iterator(); + public Iterator<Map.Entry<K, V>> iterator() { + return new Iterator<Map.Entry<K, V>>() { + Iterator<Map.Entry<K, V>> origEntries = map.entrySet() + .iterator(); + Iterator<K> addedKeys = diff.getAddedKeys().iterator(); boolean haveNext = false; - Map.Entry next; + Map.Entry<K, V> next; public boolean hasNext() { return findNext(); } - public Object next() { + public Map.Entry<K, V> next() { if (!findNext()) throw new NoSuchElementException(); - Map.Entry myNext = next; + Map.Entry<K, V> myNext = next; haveNext = false; next = null; return myNext; @@ -168,26 +174,26 @@ public abstract class MapDiff implements IDiff { if (haveNext) return true; while (true) { - Object candidateKey; - Map.Entry candidateEntry; + K candidateKey; + Map.Entry<K, V> candidateEntry; if (origEntries.hasNext()) { - candidateEntry = (Map.Entry) origEntries.next(); + candidateEntry = origEntries.next(); candidateKey = candidateEntry.getKey(); if (diff.getRemovedKeys().contains(candidateKey)) { continue; } else if (diff.getChangedKeys().contains( candidateKey)) { - candidateEntry = new DeltaMapEntry( + candidateEntry = new DeltaMapEntry<K, V>( candidateKey, diff); } else { - candidateEntry = new MapEntryWrapper( + candidateEntry = new MapEntryWrapper<K, V>( candidateEntry); } } else if (addedKeys.hasNext()) { candidateKey = addedKeys.next(); - candidateEntry = new DeltaMapEntry(candidateKey, - diff); + candidateEntry = new DeltaMapEntry<K, V>( + candidateKey, diff); } else { return false; } @@ -212,15 +218,16 @@ public abstract class MapDiff implements IDiff { } - private abstract static class AbstractMapEntry implements Map.Entry { - public Object setValue(Object arg0) { + private abstract static class AbstractMapEntry<K, V> implements + Map.Entry<K, V> { + public V setValue(Object arg0) { throw new UnsupportedOperationException(); } public boolean equals(Object obj) { if (!(obj instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) obj; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) obj; return Util.equals(this.getKey(), that.getKey()) && Util.equals(this.getValue(), that.getValue()); } @@ -236,37 +243,37 @@ public abstract class MapDiff implements IDiff { } } - private static class MapEntryWrapper extends AbstractMapEntry { - private final Entry entry; + private static class MapEntryWrapper<K, V> extends AbstractMapEntry<K, V> { + private final Entry<K, V> entry; - public MapEntryWrapper(Map.Entry entry) { + public MapEntryWrapper(Map.Entry<K, V> entry) { this.entry = entry; } - public Object getKey() { + public K getKey() { return entry.getKey(); } - public Object getValue() { + public V getValue() { return entry.getValue(); } } - private static class DeltaMapEntry extends AbstractMapEntry { - private final Object key; - private final MapDiff diff; + private static class DeltaMapEntry<K, V> extends AbstractMapEntry<K, V> { + private final K key; + private final MapDiff<K, V> diff; - public DeltaMapEntry(Object key, MapDiff diff) { + public DeltaMapEntry(K key, MapDiff<K, V> diff) { this.key = key; this.diff = diff; } - public Object getKey() { + public K getKey() { return key; } - public Object getValue() { + public V getValue() { return diff.getNewValue(key); } @@ -275,17 +282,17 @@ public abstract class MapDiff implements IDiff { /** * @return the set of keys which were added */ - public abstract Set getAddedKeys(); + public abstract Set<K> getAddedKeys(); /** * @return the set of keys which were removed */ - public abstract Set getRemovedKeys(); + public abstract Set<K> getRemovedKeys(); /** * @return the set of keys for which the value has changed */ - public abstract Set getChangedKeys(); + public abstract Set<K> getChangedKeys(); /** * Returns the old value for the given key, which must be an element of @@ -294,7 +301,7 @@ public abstract class MapDiff implements IDiff { * @param key * @return the old value for the given key. */ - public abstract Object getOldValue(Object key); + public abstract V getOldValue(Object key); /** * Returns the new value for the given key, which must be an element of @@ -303,5 +310,5 @@ public abstract class MapDiff implements IDiff { * @param key * @return the new value for the given key. */ - public abstract Object getNewValue(Object key); + public abstract V getNewValue(Object key); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ObservableMap.java index 9f835a16..4a229e16 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/ObservableMap.java @@ -29,18 +29,22 @@ import org.eclipse.core.databinding.observable.Realm; * listeners may be invoked from any thread. * </p> * + * @param <K> + * @param <V> + * * @since 1.0 */ -public class ObservableMap extends AbstractObservable implements IObservableMap { +public class ObservableMap<K, V> extends AbstractObservable implements + IObservableMap<K, V> { - protected Map wrappedMap; + protected Map<K, V> wrappedMap; private boolean stale = false; /** * @param wrappedMap */ - public ObservableMap(Map wrappedMap) { + public ObservableMap(Map<K, V> wrappedMap) { this(Realm.getDefault(), wrappedMap); } @@ -48,16 +52,18 @@ public class ObservableMap extends AbstractObservable implements IObservableMap * @param realm * @param wrappedMap */ - public ObservableMap(Realm realm, Map wrappedMap) { + public ObservableMap(Realm realm, Map<K, V> wrappedMap) { super(realm); this.wrappedMap = wrappedMap; } - public synchronized void addMapChangeListener(IMapChangeListener listener) { + public synchronized void addMapChangeListener( + IMapChangeListener<K, V> listener) { addListener(MapChangeEvent.TYPE, listener); } - public synchronized void removeMapChangeListener(IMapChangeListener listener) { + public synchronized void removeMapChangeListener( + IMapChangeListener<K, V> listener) { removeListener(MapChangeEvent.TYPE, listener); } @@ -79,13 +85,13 @@ public class ObservableMap extends AbstractObservable implements IObservableMap ObservableTracker.getterCalled(this); } - protected void fireMapChange(MapDiff diff) { + protected void fireMapChange(MapDiff<K, V> diff) { checkRealm(); // fire general change event first super.fireChange(); - fireEvent(new MapChangeEvent(this, diff)); + fireEvent(new MapChangeEvent<K, V>(this, diff)); } public boolean containsKey(Object key) { @@ -98,12 +104,12 @@ public class ObservableMap extends AbstractObservable implements IObservableMap return wrappedMap.containsValue(value); } - public Set entrySet() { + public Set<Entry<K, V>> entrySet() { getterCalled(); return wrappedMap.entrySet(); } - public Object get(Object key) { + public V get(Object key) { getterCalled(); return wrappedMap.get(key); } @@ -113,7 +119,7 @@ public class ObservableMap extends AbstractObservable implements IObservableMap return wrappedMap.isEmpty(); } - public Set keySet() { + public Set<K> keySet() { getterCalled(); return wrappedMap.keySet(); } @@ -123,7 +129,7 @@ public class ObservableMap extends AbstractObservable implements IObservableMap return wrappedMap.size(); } - public Collection values() { + public Collection<V> values() { getterCalled(); return wrappedMap.values(); } @@ -155,11 +161,11 @@ public class ObservableMap extends AbstractObservable implements IObservableMap } } - public Object put(Object key, Object value) { + public V put(K key, V value) { throw new UnsupportedOperationException(); } - public Object remove(Object key) { + public V remove(Object key) { throw new UnsupportedOperationException(); } @@ -167,7 +173,7 @@ public class ObservableMap extends AbstractObservable implements IObservableMap throw new UnsupportedOperationException(); } - public void putAll(Map arg0) { + public void putAll(Map<? extends K, ? extends V> arg0) { throw new UnsupportedOperationException(); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/WritableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/WritableMap.java index 8a8a0d92..d90724bb 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/WritableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/map/WritableMap.java @@ -31,9 +31,12 @@ import org.eclipse.core.internal.databinding.observable.Util; * the {@link Realm#isCurrent() current realm}. Methods for adding and removing * listeners may be invoked from any thread. * </p> + * + * @param <K> + * @param <V> * @since 1.0 */ -public class WritableMap extends ObservableMap { +public class WritableMap<K, V> extends ObservableMap<K, V> { private final Object keyType; private final Object valueType; @@ -43,7 +46,7 @@ public class WritableMap extends ObservableMap { public WritableMap() { this(Realm.getDefault(), null, null); } - + /** * Constructs a new WritableMap on the given realm. * @@ -76,7 +79,7 @@ public class WritableMap extends ObservableMap { * @since 1.2 */ public WritableMap(Realm realm, Object keyType, Object valueType) { - super(realm, new HashMap()); + super(realm, new HashMap<K, V>()); this.keyType = keyType; this.valueType = valueType; } @@ -96,22 +99,22 @@ public class WritableMap extends ObservableMap { } /** - * Associates the provided <code>value</code> with the <code>key</code>. Must be invoked from the current realm. + * Associates the provided <code>value</code> with the <code>key</code>. + * Must be invoked from the current realm. */ - public Object put(Object key, Object value) { + public V put(K key, V value) { checkRealm(); boolean containedKeyBefore = wrappedMap.containsKey(key); - Object result = wrappedMap.put(key, value); + V result = wrappedMap.put(key, value); boolean containedKeyAfter = wrappedMap.containsKey(key); if (containedKeyBefore != containedKeyAfter || !Util.equals(result, value)) { - MapDiff diff; + MapDiff<K, V> diff; if (containedKeyBefore) { if (containedKeyAfter) { - diff = Diffs - .createMapDiffSingleChange(key, result, value); + diff = Diffs.createMapDiffSingleChange(key, result, value); } else { diff = Diffs.createMapDiffSingleRemove(key, result); } @@ -124,42 +127,44 @@ public class WritableMap extends ObservableMap { } /** - * Removes the value with the provide <code>key</code>. Must be invoked from the current realm. + * Removes the value with the provide <code>key</code>. Must be invoked from + * the current realm. */ - public Object remove(Object key) { + public V remove(Object key) { checkRealm(); if (wrappedMap.containsKey(key)) { - Object result = wrappedMap.remove(key); - fireMapChange(Diffs.createMapDiffSingleRemove(key, result)); + V result = wrappedMap.remove(key); + fireMapChange(Diffs.createMapDiffSingleRemove((K) key, result)); return result; } return null; } /** - * Clears the map. Must be invoked from the current realm. + * Clears the map. Must be invoked from the current realm. */ public void clear() { checkRealm(); if (!isEmpty()) { - Map copy = new HashMap(wrappedMap); + Map<K, V> copy = new HashMap<K, V>(wrappedMap); wrappedMap.clear(); fireMapChange(Diffs.createMapDiffRemoveAll(copy)); } } /** - * Adds the provided <code>map</code>'s contents to this map. Must be invoked from the current realm. + * Adds the provided <code>map</code>'s contents to this map. Must be + * invoked from the current realm. */ - public void putAll(Map map) { + public void putAll(Map<? extends K, ? extends V> map) { checkRealm(); - Set addedKeys = new HashSet(map.size()); - Map changes = new HashMap(map.size()); - for (Iterator it = map.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Entry) it.next(); + Set<K> addedKeys = new HashSet<K>(map.size()); + Map<K, V> changes = new HashMap<K, V>(map.size()); + for (Iterator<?> it = map.entrySet().iterator(); it.hasNext();) { + Map.Entry<? extends K, ? extends V> entry = (Map.Entry<? extends K, ? extends V>) it + .next(); boolean add = !wrappedMap.containsKey(entry.getKey()); - Object previousValue = wrappedMap.put(entry.getKey(), entry - .getValue()); + V previousValue = wrappedMap.put(entry.getKey(), entry.getValue()); if (add) { addedKeys.add(entry.getKey()); } else { @@ -167,7 +172,8 @@ public class WritableMap extends ObservableMap { } } if (!addedKeys.isEmpty() || !changes.isEmpty()) { - fireMapChange(Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET, + Set<K> removedKeys = Collections.emptySet(); + fireMapChange(Diffs.createMapDiff(addedKeys, removedKeys, changes.keySet(), changes, wrappedMap)); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/IObservableFactory.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/IObservableFactory.java index e113f141..d71affc2 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/IObservableFactory.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/IObservableFactory.java @@ -16,9 +16,15 @@ import org.eclipse.core.databinding.observable.IObservable; /** * Generates an {@link IObservable} when passed a target instance. * + * @param <T> + * type of the target + * @param <E> + * type of the observable constructed by this factory; this type must + * extend or implement IObservable + * * @since 1.0 */ -public interface IObservableFactory { +public interface IObservableFactory<T, E extends IObservable> { /** * Creates an observable for the given target object. @@ -26,6 +32,6 @@ public interface IObservableFactory { * @param target * @return the new observable */ - public IObservable createObservable(Object target); + public E createObservable(T target); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/MasterDetailObservables.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/MasterDetailObservables.java index 203a1cf9..16e9e5f8 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/MasterDetailObservables.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/masterdetail/MasterDetailObservables.java @@ -39,6 +39,10 @@ public class MasterDetailObservables { * factory. This can be used to create observable values that represent a * property of a selected object in a table. * + * @param <M> + * type of the master observable + * @param <T> + * type of the inner detail observable * @param master * the observable value to track * @param detailFactory @@ -51,9 +55,12 @@ public class MasterDetailObservables { * value of the given master value, behaves like the observable * value created by the factory for that current value. */ - public static IObservableValue detailValue(IObservableValue master, - IObservableFactory detailFactory, Object detailType) { - return new DetailObservableValue(master, detailFactory, detailType); + public static <M, T> IObservableValue<T> detailValue( + IObservableValue<M> master, + IObservableFactory<? super M, IObservableValue<T>> detailFactory, + Object detailType) { + return new DetailObservableValue<M, T>(master, detailFactory, + detailType); } /** @@ -61,6 +68,10 @@ public class MasterDetailObservables { * factory. This can be used to create observable lists that represent a * list property of a selected object in a table. * + * @param <M> + * type of the master observable + * @param <E> + * type of the elements in the inner observable set * @param master * the observable value to track * @param detailFactory @@ -73,9 +84,11 @@ public class MasterDetailObservables { * current value of the given master value, behaves like the * observable list created by the factory for that current value. */ - public static IObservableList detailList(IObservableValue master, - IObservableFactory detailFactory, Object detailElementType) { - return new DetailObservableList(detailFactory, master, + public static <M, E> IObservableList<E> detailList( + IObservableValue<M> master, + IObservableFactory<? super M, IObservableList<E>> detailFactory, + Object detailElementType) { + return new DetailObservableList<M, E>(detailFactory, master, detailElementType); } @@ -84,6 +97,10 @@ public class MasterDetailObservables { * factory. This can be used to create observable sets that represent a set * property of a selected object in a table. * + * @param <M> + * type of the master observable + * @param <E> + * type of the elements in the inner observable set * @param master * the observable value to track * @param detailFactory @@ -96,9 +113,12 @@ public class MasterDetailObservables { * current value of the given master value, behaves like the * observable set created by the factory for that current value. */ - public static IObservableSet detailSet(IObservableValue master, - IObservableFactory detailFactory, Object detailElementType) { - return new DetailObservableSet(detailFactory, master, detailElementType); + public static <M, E> IObservableSet<E> detailSet( + IObservableValue<M> master, + IObservableFactory<? super M, IObservableSet<E>> detailFactory, + Object detailElementType) { + return new DetailObservableSet<M, E>(detailFactory, master, + detailElementType); } /** @@ -106,18 +126,25 @@ public class MasterDetailObservables { * factory. This can be used to create observable maps that represent a map * property of a selected object in a table. * + * @param <M> + * type of the master observable + * @param <K> + * type of the keys to the inner observable map + * @param <V> + * type of the values in the inner observable map * @param master * the observable value to track * @param detailFactory - * a factory for createing {@link IObservableMap} instances given + * a factory for creating {@link IObservableMap} instances given * a current value of the master * @return an observable map that, for any current value of the given master * value, behaves like the observable map created by the factory for * that current value. * @since 1.1 */ - public static IObservableMap detailMap(IObservableValue master, - IObservableFactory detailFactory) { + public static <M, K, V> IObservableMap<K, V> detailMap( + IObservableValue<M> master, + IObservableFactory<M, IObservableMap<K, V>> detailFactory) { return detailMap(master, detailFactory, null, null); } @@ -126,10 +153,16 @@ public class MasterDetailObservables { * factory. This can be used to create observable maps that represent a map * property of a selected object in a table. * + * @param <M> + * type of the master observable + * @param <K> + * type of the keys to the inner observable map + * @param <V> + * type of the values in the inner observable map * @param master * the observable value to track * @param detailFactory - * a factory for createing {@link IObservableMap} instances given + * a factory for creating {@link IObservableMap} instances given * a current value of the master * @param detailKeyType * the element type of the detail observable map's key set, @@ -143,11 +176,12 @@ public class MasterDetailObservables { * that current value. * @since 1.2 */ - public static IObservableMap detailMap(IObservableValue master, - IObservableFactory detailFactory, Object detailKeyType, - Object detailValueType) { - return new DetailObservableMap(detailFactory, master, detailKeyType, - detailValueType); + public static <M, K, V> IObservableMap<K, V> detailMap( + IObservableValue<M> master, + IObservableFactory<? super M, IObservableMap<K, V>> detailFactory, + Object detailKeyType, Object detailValueType) { + return new DetailObservableMap<M, K, V>(detailFactory, master, + detailKeyType, detailValueType); } /** @@ -165,6 +199,10 @@ public class MasterDetailObservables { * by the specified observable factory. * </p> * + * @param <M> + * type of the master observables in the master list + * @param <E> + * type of the detail elements * @param masterList * The master observable list. * @param detailFactory @@ -179,10 +217,12 @@ public class MasterDetailObservables { * * @since 1.4 */ - public static IObservableList detailValues(IObservableList masterList, - IObservableFactory detailFactory, Object detailType) { - return new ListDetailValueObservableList(masterList, detailFactory, - detailType); + public static <M, E> IObservableList<E> detailValues( + IObservableList<M> masterList, + IObservableFactory<? super M, IObservableValue<E>> detailFactory, + Object detailType) { + return new ListDetailValueObservableList<M, E>(masterList, + detailFactory, detailType); } /** @@ -204,6 +244,10 @@ public class MasterDetailObservables { * factory. * </p> * + * @param <M> + * type of the master observables in the master set + * @param <E> + * type of the detail elements * @param masterSet * The master observable set. * @param detailFactory @@ -219,9 +263,11 @@ public class MasterDetailObservables { * * @since 1.4 */ - public static IObservableMap detailValues(IObservableSet masterSet, - IObservableFactory detailFactory, Object detailType) { - return new SetDetailValueObservableMap(masterSet, detailFactory, + public static <M, E> IObservableMap<M, E> detailValues( + IObservableSet<M> masterSet, + IObservableFactory<? super M, IObservableValue<E>> detailFactory, + Object detailType) { + return new SetDetailValueObservableMap<M, E>(masterSet, detailFactory, detailType); } @@ -244,6 +290,16 @@ public class MasterDetailObservables { * observable factory. * </p> * + * @param <K> + * type of the keys (the keys to both the given master observable + * map and the keys to the returned detail map, both of which are + * the same set of keys) + * @param <M> + * type of the master observables in the master set, being the + * values of the given master observable map + * @param <E> + * type of the detail elements, being the values of the returned + * detail map * @param masterMap * The master observable map. * @param detailFactory @@ -259,9 +315,11 @@ public class MasterDetailObservables { * * @since 1.4 */ - public static IObservableMap detailValues(IObservableMap masterMap, - IObservableFactory detailFactory, Object detailType) { - return new MapDetailValueObservableMap(masterMap, detailFactory, - detailType); + public static <K, M, E> IObservableMap<K, E> detailValues( + IObservableMap<K, M> masterMap, + IObservableFactory<? super M, IObservableValue<E>> detailFactory, + Object detailType) { + return new MapDetailValueObservableMap<K, M, E>(masterMap, + detailFactory, detailType); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java index c446b3f1..7a46c874 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/AbstractObservableSet.java @@ -30,17 +30,19 @@ import org.eclipse.core.databinding.observable.Realm; * listeners may be invoked from any thread. * </p> * + * @param <E> + * * @since 1.0 */ -public abstract class AbstractObservableSet extends AbstractObservable implements - IObservableSet { +public abstract class AbstractObservableSet<E> extends AbstractObservable + implements IObservableSet<E> { private boolean stale = false; protected AbstractObservableSet() { this(Realm.getDefault()); } - + protected void firstListenerAdded() { super.firstListenerAdded(); } @@ -48,34 +50,36 @@ public abstract class AbstractObservableSet extends AbstractObservable implement protected void lastListenerRemoved() { super.lastListenerRemoved(); } - + protected AbstractObservableSet(Realm realm) { super(realm); } - - public synchronized void addSetChangeListener(ISetChangeListener listener) { + + public synchronized void addSetChangeListener( + ISetChangeListener<? super E> listener) { addListener(SetChangeEvent.TYPE, listener); } - public synchronized void removeSetChangeListener(ISetChangeListener listener) { + public synchronized void removeSetChangeListener( + ISetChangeListener<? super E> listener) { removeListener(SetChangeEvent.TYPE, listener); } - protected abstract Set getWrappedSet(); - - protected void fireSetChange(SetDiff diff) { + protected abstract Set<E> getWrappedSet(); + + protected void fireSetChange(SetDiff<E> diff) { // fire general change event first super.fireChange(); - fireEvent(new SetChangeEvent(this, diff)); + fireEvent(new SetChangeEvent<E>(this, diff)); } - + public boolean contains(Object o) { getterCalled(); return getWrappedSet().contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return getWrappedSet().containsAll(c); } @@ -95,10 +99,10 @@ public abstract class AbstractObservableSet extends AbstractObservable implement return getWrappedSet().isEmpty(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - final Iterator wrappedIterator = getWrappedSet().iterator(); - return new Iterator() { + final Iterator<E> wrappedIterator = getWrappedSet().iterator(); + return new Iterator<E>() { public void remove() { throw new UnsupportedOperationException(); @@ -109,7 +113,7 @@ public abstract class AbstractObservableSet extends AbstractObservable implement return wrappedIterator.hasNext(); } - public Object next() { + public E next() { ObservableTracker.getterCalled(AbstractObservableSet.this); return wrappedIterator.next(); } @@ -126,7 +130,7 @@ public abstract class AbstractObservableSet extends AbstractObservable implement return getWrappedSet().toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); return getWrappedSet().toArray(a); } @@ -140,11 +144,11 @@ public abstract class AbstractObservableSet extends AbstractObservable implement ObservableTracker.getterCalled(this); } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } @@ -152,11 +156,11 @@ public abstract class AbstractObservableSet extends AbstractObservable implement throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -187,8 +191,8 @@ public abstract class AbstractObservableSet extends AbstractObservable implement } } - protected void fireChange() { - throw new RuntimeException("fireChange should not be called, use fireSetChange() instead"); //$NON-NLS-1$ + throw new RuntimeException( + "fireChange should not be called, use fireSetChange() instead"); //$NON-NLS-1$ } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ComputedSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ComputedSet.java index 827dc655..1f632564 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ComputedSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ComputedSet.java @@ -66,10 +66,12 @@ import org.eclipse.core.databinding.observable.value.IObservableValue; * System.out.println(primes); // => "[2, 3, 5, 7, 11, 13, 17, 19]" * </pre> * + * @param <E> + * * @since 1.2 */ -public abstract class ComputedSet extends AbstractObservableSet { - private Set cachedSet = new HashSet(); +public abstract class ComputedSet<E> extends AbstractObservableSet<E> { + private Set<E> cachedSet = new HashSet<E>(); private boolean dirty = true; private boolean stale = false; @@ -144,25 +146,30 @@ public abstract class ComputedSet extends AbstractObservableSet { * </p> * */ - private class PrivateInterface implements Runnable, IChangeListener, - IStaleListener { - public void run() { - cachedSet = calculate(); - if (cachedSet == null) - cachedSet = Collections.EMPTY_SET; + private class PrivateChangeInterface implements IChangeListener { + public void handleChange(ChangeEvent event) { + makeDirty(); } + } + private class PrivateStaleInterface implements IStaleListener { public void handleStale(StaleEvent event) { if (!dirty) makeStale(); } + } - public void handleChange(ChangeEvent event) { - makeDirty(); + private class PrivateRunnableInterface implements Runnable { + public void run() { + cachedSet = calculate(); + if (cachedSet == null) + cachedSet = Collections.emptySet(); } } - private PrivateInterface privateInterface = new PrivateInterface(); + private IChangeListener privateChangeInterface = new PrivateChangeInterface(); + private IStaleListener privateStaleInterface = new PrivateStaleInterface(); + private Runnable privateRunnableInterface = new PrivateRunnableInterface(); private Object elementType; @@ -170,23 +177,23 @@ public abstract class ComputedSet extends AbstractObservableSet { return doGetSet().size(); } - private final Set getSet() { + private final Set<E> getSet() { getterCalled(); return doGetSet(); } - protected Set getWrappedSet() { + protected Set<E> getWrappedSet() { return doGetSet(); } - final Set doGetSet() { + final Set<E> doGetSet() { if (dirty) { // This line will do the following: // - Run the calculate method // - While doing so, add any observable that is touched to the // dependencies list IObservable[] newDependencies = ObservableTracker.runAndMonitor( - privateInterface, privateInterface, null); + privateRunnableInterface, privateChangeInterface, null); // If any dependencies are stale, a stale event will be fired here // even if we were already stale before recomputing. This is in case @@ -201,7 +208,7 @@ public abstract class ComputedSet extends AbstractObservableSet { if (!stale) { for (int i = 0; i < newDependencies.length; i++) { - newDependencies[i].addStaleListener(privateInterface); + newDependencies[i].addStaleListener(privateStaleInterface); } } @@ -221,7 +228,7 @@ public abstract class ComputedSet extends AbstractObservableSet { * * @return the object's set. */ - protected abstract Set calculate(); + protected abstract Set<E> calculate(); private void makeDirty() { if (!dirty) { @@ -232,23 +239,23 @@ public abstract class ComputedSet extends AbstractObservableSet { stopListening(); // copy the old set - final Set oldSet = new HashSet(cachedSet); + final Set<E> oldSet = new HashSet<E>(cachedSet); // Fire the "dirty" event. This implementation recomputes the new // set lazily. - fireSetChange(new SetDiff() { - SetDiff delegate; + fireSetChange(new SetDiff<E>() { + SetDiff<E> delegate; - private SetDiff getDelegate() { + private SetDiff<E> getDelegate() { if (delegate == null) delegate = Diffs.computeSetDiff(oldSet, getSet()); return delegate; } - public Set getAdditions() { + public Set<E> getAdditions() { return getDelegate().getAdditions(); } - public Set getRemovals() { + public Set<E> getRemovals() { return getDelegate().getRemovals(); } }); @@ -260,8 +267,8 @@ public abstract class ComputedSet extends AbstractObservableSet { for (int i = 0; i < dependencies.length; i++) { IObservable observable = dependencies[i]; - observable.removeChangeListener(privateInterface); - observable.removeStaleListener(privateInterface); + observable.removeChangeListener(privateChangeInterface); + observable.removeStaleListener(privateStaleInterface); } dependencies = null; } @@ -291,7 +298,8 @@ public abstract class ComputedSet extends AbstractObservableSet { computeSetForListeners(); } - public synchronized void addSetChangeListener(ISetChangeListener listener) { + public synchronized void addSetChangeListener( + ISetChangeListener<? super E> listener) { super.addSetChangeListener(listener); // If somebody is listening, we need to make sure we attach our own // listeners diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/DecoratingObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/DecoratingObservableSet.java index 38092bb6..2bd7b8a2 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/DecoratingObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/DecoratingObservableSet.java @@ -17,14 +17,16 @@ import org.eclipse.core.databinding.observable.DecoratingObservableCollection; /** * An observable set which decorates another observable set. * + * @param <E> + * * @since 1.2 */ -public class DecoratingObservableSet extends DecoratingObservableCollection - implements IObservableSet { +public class DecoratingObservableSet<E> extends + DecoratingObservableCollection<E> implements IObservableSet<E> { - private IObservableSet decorated; + private IObservableSet<E> decorated; - private ISetChangeListener setChangeListener; + private ISetChangeListener<E> setChangeListener; /** * Constructs a DecoratingObservableSet which decorates the given @@ -34,7 +36,7 @@ public class DecoratingObservableSet extends DecoratingObservableCollection * the observable set being decorated * @param disposeDecoratedOnDispose */ - public DecoratingObservableSet(IObservableSet decorated, + public DecoratingObservableSet(IObservableSet<E> decorated, boolean disposeDecoratedOnDispose) { super(decorated, disposeDecoratedOnDispose); this.decorated = decorated; @@ -45,18 +47,20 @@ public class DecoratingObservableSet extends DecoratingObservableCollection decorated.clear(); } - public synchronized void addSetChangeListener(ISetChangeListener listener) { + public synchronized void addSetChangeListener( + ISetChangeListener<? super E> listener) { addListener(SetChangeEvent.TYPE, listener); } - public synchronized void removeSetChangeListener(ISetChangeListener listener) { + public synchronized void removeSetChangeListener( + ISetChangeListener<? super E> listener) { removeListener(SetChangeEvent.TYPE, listener); } - protected void fireSetChange(SetDiff diff) { + protected void fireSetChange(SetDiff<E> diff) { // fire general change event first super.fireChange(); - fireEvent(new SetChangeEvent(this, diff)); + fireEvent(new SetChangeEvent<E>(this, diff)); } protected void fireChange() { @@ -66,8 +70,8 @@ public class DecoratingObservableSet extends DecoratingObservableCollection protected void firstListenerAdded() { if (setChangeListener == null) { - setChangeListener = new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { + setChangeListener = new ISetChangeListener<E>() { + public void handleSetChange(SetChangeEvent<E> event) { DecoratingObservableSet.this.handleSetChange(event); } }; @@ -93,7 +97,7 @@ public class DecoratingObservableSet extends DecoratingObservableCollection * @param event * the change event received from the decorated observable */ - protected void handleSetChange(final SetChangeEvent event) { + protected void handleSetChange(final SetChangeEvent<E> event) { fireSetChange(event.diff); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/IObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/IObservableSet.java index 358cb0cd..0c3df793 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/IObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/IObservableSet.java @@ -21,6 +21,8 @@ import org.eclipse.core.databinding.observable.IObservableCollection; /** * A set whose changes can be tracked by set change listeners. * + * @param <E> + * * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that * implement this interface. Note that direct implementers of this @@ -33,17 +35,17 @@ import org.eclipse.core.databinding.observable.IObservableCollection; * @since 1.0 * */ -public interface IObservableSet extends Set, IObservableCollection { +public interface IObservableSet<E> extends Set<E>, IObservableCollection<E> { /** * @param listener */ - public void addSetChangeListener(ISetChangeListener listener); + public void addSetChangeListener(ISetChangeListener<? super E> listener); /** * @param listener */ - public void removeSetChangeListener(ISetChangeListener listener); + public void removeSetChangeListener(ISetChangeListener<? super E> listener); /** * @return the element type or <code>null</code> if untyped @@ -68,7 +70,7 @@ public interface IObservableSet extends Set, IObservableCollection { /** * @TrackedGetter */ - Iterator iterator(); + Iterator<E> iterator(); /** * @TrackedGetter @@ -78,14 +80,14 @@ public interface IObservableSet extends Set, IObservableCollection { /** * @TrackedGetter */ - Object[] toArray(Object a[]); + <T> T[] toArray(T a[]); // Modification Operations /** * @TrackedGetter */ - boolean add(Object o); + boolean add(E o); /** * @TrackedGetter @@ -97,22 +99,22 @@ public interface IObservableSet extends Set, IObservableCollection { /** * @TrackedGetter */ - boolean containsAll(Collection c); + boolean containsAll(Collection<?> c); /** * @TrackedGetter */ - boolean addAll(Collection c); + boolean addAll(Collection<? extends E> c); /** * @TrackedGetter */ - boolean retainAll(Collection c); + boolean retainAll(Collection<?> c); /** * @TrackedGetter */ - boolean removeAll(Collection c); + boolean removeAll(Collection<?> c); // Comparison and hashing diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ISetChangeListener.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ISetChangeListener.java index 51c429a3..f0b1d8db 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ISetChangeListener.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ISetChangeListener.java @@ -16,10 +16,12 @@ import org.eclipse.core.databinding.observable.IObservablesListener; /** * Listener for changes to observable sets. * + * @param <E> + * * @since 1.0 * */ -public interface ISetChangeListener extends IObservablesListener { +public interface ISetChangeListener<E> extends IObservablesListener { /** * Handle a change to an observable set. The given event object must only be @@ -30,6 +32,6 @@ public interface ISetChangeListener extends IObservablesListener { * @param event * the event */ - void handleSetChange(SetChangeEvent event); + void handleSetChange(SetChangeEvent<E> event); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ListToSetAdapter.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ListToSetAdapter.java index e145fb3c..43fc6f1d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ListToSetAdapter.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ListToSetAdapter.java @@ -12,6 +12,7 @@ package org.eclipse.core.databinding.observable.set; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.eclipse.core.databinding.observable.Diffs; @@ -31,22 +32,23 @@ import org.eclipse.core.databinding.observable.list.ListDiffEntry; * listeners may be invoked from any thread. * </p> * + * @param <E> * @since 1.0 * */ -public class ListToSetAdapter extends ObservableSet { +public class ListToSetAdapter<E> extends ObservableSet<E> { - private final IObservableList list; + private final IObservableList<E> list; - private IListChangeListener listener = new IListChangeListener() { + private IListChangeListener<E> listener = new IListChangeListener<E>() { - public void handleListChange(ListChangeEvent event) { - Set added = new HashSet(); - Set removed = new HashSet(); - ListDiffEntry[] differences = event.diff.getDifferences(); - for (int i = 0; i < differences.length; i++) { - ListDiffEntry entry = differences[i]; - Object element = entry.getElement(); + public void handleListChange(ListChangeEvent<E> event) { + Set<E> added = new HashSet<E>(); + Set<E> removed = new HashSet<E>(); + List<ListDiffEntry<E>> differences = event.diff + .getDifferencesAsList(); + for (ListDiffEntry<E> entry : differences) { + E element = entry.getElement(); if (entry.isAddition()) { if (wrappedSet.add(element)) { if (!removed.remove(element)) @@ -66,8 +68,8 @@ public class ListToSetAdapter extends ObservableSet { /** * @param list */ - public ListToSetAdapter(IObservableList list) { - super(list.getRealm(), new HashSet(), list.getElementType()); + public ListToSetAdapter(IObservableList<E> list) { + super(list.getRealm(), new HashSet<E>(), list.getElementType()); this.list = list; wrappedSet.addAll(list); this.list.addListChangeListener(listener); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/MappedSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/MappedSet.java index 9f03e26e..7e35d488 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/MappedSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/MappedSet.java @@ -38,6 +38,8 @@ import org.eclipse.core.databinding.observable.map.MapDiff; * * @deprecated This class is deprecated. */ +// OK to hide warnings on a deprecated class +@SuppressWarnings({ "rawtypes", "unchecked" }) public class MappedSet extends ObservableSet { private final IObservableMap wrappedMap; @@ -50,7 +52,8 @@ public class MappedSet extends ObservableSet { private ISetChangeListener domainListener = new ISetChangeListener() { public void handleSetChange(SetChangeEvent event) { Set additions = new HashSet(); - for (Iterator it = event.diff.getAdditions().iterator(); it.hasNext();) { + for (Iterator it = event.diff.getAdditions().iterator(); it + .hasNext();) { Object added = it.next(); Object mapValue = wrappedMap.get(added); if (handleAddition(mapValue)) { @@ -58,7 +61,8 @@ public class MappedSet extends ObservableSet { } } Set removals = new HashSet(); - for (Iterator it = event.diff.getRemovals().iterator(); it.hasNext();) { + for (Iterator it = event.diff.getRemovals().iterator(); it + .hasNext();) { Object removed = it.next(); Object mapValue = wrappedMap.get(removed); if (handleRemoval(mapValue)) { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ObservableSet.java index 4ee55004..3b4b49d5 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/ObservableSet.java @@ -30,41 +30,45 @@ import org.eclipse.core.databinding.observable.Realm; * listeners may be invoked from any thread. * </p> * + * @param <E> + * * @since 1.0 * */ -public abstract class ObservableSet extends AbstractObservable implements - IObservableSet { +public abstract class ObservableSet<E> extends AbstractObservable implements + IObservableSet<E> { - protected Set wrappedSet; + protected Set<E> wrappedSet; private boolean stale = false; protected Object elementType; - protected ObservableSet(Set wrappedSet, Object elementType) { + protected ObservableSet(Set<E> wrappedSet, Object elementType) { this(Realm.getDefault(), wrappedSet, elementType); } - protected ObservableSet(Realm realm, Set wrappedSet, Object elementType) { + protected ObservableSet(Realm realm, Set<E> wrappedSet, Object elementType) { super(realm); this.wrappedSet = wrappedSet; this.elementType = elementType; } - public synchronized void addSetChangeListener(ISetChangeListener listener) { + public synchronized void addSetChangeListener( + ISetChangeListener<? super E> listener) { addListener(SetChangeEvent.TYPE, listener); } - public synchronized void removeSetChangeListener(ISetChangeListener listener) { + public synchronized void removeSetChangeListener( + ISetChangeListener<? super E> listener) { removeListener(SetChangeEvent.TYPE, listener); } - protected void fireSetChange(SetDiff diff) { + protected void fireSetChange(SetDiff<E> diff) { // fire general change event first super.fireChange(); - fireEvent(new SetChangeEvent(this, diff)); + fireEvent(new SetChangeEvent<E>(this, diff)); } public boolean contains(Object o) { @@ -72,7 +76,7 @@ public abstract class ObservableSet extends AbstractObservable implements return wrappedSet.contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return wrappedSet.containsAll(c); } @@ -92,10 +96,10 @@ public abstract class ObservableSet extends AbstractObservable implements return wrappedSet.isEmpty(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - final Iterator wrappedIterator = wrappedSet.iterator(); - return new Iterator() { + final Iterator<E> wrappedIterator = wrappedSet.iterator(); + return new Iterator<E>() { public void remove() { throw new UnsupportedOperationException(); @@ -106,7 +110,7 @@ public abstract class ObservableSet extends AbstractObservable implements return wrappedIterator.hasNext(); } - public Object next() { + public E next() { ObservableTracker.getterCalled(ObservableSet.this); return wrappedIterator.next(); } @@ -123,7 +127,7 @@ public abstract class ObservableSet extends AbstractObservable implements return wrappedSet.toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); return wrappedSet.toArray(a); } @@ -137,11 +141,11 @@ public abstract class ObservableSet extends AbstractObservable implements ObservableTracker.getterCalled(this); } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } @@ -149,11 +153,11 @@ public abstract class ObservableSet extends AbstractObservable implements throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -188,7 +192,7 @@ public abstract class ObservableSet extends AbstractObservable implements * @param wrappedSet * The wrappedSet to set. */ - protected void setWrappedSet(Set wrappedSet) { + protected void setWrappedSet(Set<E> wrappedSet) { this.wrappedSet = wrappedSet; } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetChangeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetChangeEvent.java index 4873885e..7623dd2c 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetChangeEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetChangeEvent.java @@ -18,10 +18,12 @@ import org.eclipse.core.databinding.observable.ObservableEvent; * List change event describing an incremental change of an * {@link IObservableSet} object. * + * @param <E> + * * @since 1.0 * */ -public class SetChangeEvent extends ObservableEvent { +public class SetChangeEvent<E> extends ObservableEvent<SetChangeEvent<E>> { /** * @@ -33,7 +35,13 @@ public class SetChangeEvent extends ObservableEvent { * Description of the change to the source observable set. Listeners must * not change this field. */ - public SetDiff diff; + public SetDiff<E> diff; + + /** + * Always identical to <code>EventObject.source</code> but the type + * information is maintained. + */ + private IObservableSet<E> typedSource; /** * Creates a new set change event. @@ -43,8 +51,9 @@ public class SetChangeEvent extends ObservableEvent { * @param diff * the set change */ - public SetChangeEvent(IObservableSet source, SetDiff diff) { + public SetChangeEvent(IObservableSet<E> source, SetDiff<E> diff) { super(source); + this.typedSource = source; this.diff = diff; } @@ -53,12 +62,12 @@ public class SetChangeEvent extends ObservableEvent { * * @return the observable set from which this event originated */ - public IObservableSet getObservableSet() { - return (IObservableSet) getSource(); + public IObservableSet<E> getObservableSet() { + return typedSource; } protected void dispatch(IObservablesListener listener) { - ((ISetChangeListener) listener).handleSetChange(this); + ((ISetChangeListener<E>) listener).handleSetChange(this); } protected Object getListenerType() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetDiff.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetDiff.java index 9b93970a..7fbd5a0d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetDiff.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/SetDiff.java @@ -20,20 +20,21 @@ import java.util.Set; import org.eclipse.core.databinding.observable.IDiff; /** + * @param <E> * @since 1.0 * */ -public abstract class SetDiff implements IDiff { +public abstract class SetDiff<E> implements IDiff { /** * @return the set of added elements */ - public abstract Set getAdditions(); + public abstract Set<E> getAdditions(); /** * @return the set of removed elements */ - public abstract Set getRemovals(); + public abstract Set<E> getRemovals(); /** * Returns true if the diff has no added or removed elements. @@ -52,7 +53,7 @@ public abstract class SetDiff implements IDiff { * the set to which the diff will be applied * @since 1.2 */ - public void applyTo(Set set) { + public void applyTo(Set<E> set) { set.addAll(getAdditions()); set.removeAll(getRemovals()); } @@ -72,35 +73,35 @@ public abstract class SetDiff implements IDiff { * were passed to the {@link #applyTo(Set)} method. * @since 1.3 */ - public Set simulateOn(Set set) { - return new DeltaSet(set, this); + public Set<E> simulateOn(Set<E> set) { + return new DeltaSet<E>(set, this); } - private static class DeltaSet extends AbstractSet { - private Set original; - private final SetDiff diff; + private static class DeltaSet<E> extends AbstractSet<E> { + private Set<E> original; + private final SetDiff<E> diff; - public DeltaSet(Set original, SetDiff diff) { + public DeltaSet(Set<E> original, SetDiff<E> diff) { this.original = original; this.diff = diff; } - public Iterator iterator() { - return new Iterator() { - Iterator orig = original.iterator(); - Iterator add = diff.getAdditions().iterator(); + public Iterator<E> iterator() { + return new Iterator<E>() { + Iterator<E> orig = original.iterator(); + Iterator<E> add = diff.getAdditions().iterator(); boolean haveNext = false; - Object next; + E next; public boolean hasNext() { return findNext(); } - public Object next() { + public E next() { if (!findNext()) throw new NoSuchElementException(); - Object myNext = next; + E myNext = next; haveNext = false; next = null; return myNext; @@ -110,7 +111,7 @@ public abstract class SetDiff implements IDiff { if (haveNext) return true; while (true) { - Object candidate; + E candidate; if (orig.hasNext()) candidate = orig.next(); else if (add.hasNext()) @@ -149,14 +150,13 @@ public abstract class SetDiff implements IDiff { */ public String toString() { StringBuffer buffer = new StringBuffer(); - buffer.append(getClass().getName()).append("{additions [") //$NON-NLS-1$ - .append( - getAdditions() != null ? getAdditions().toString() - : "null") //$NON-NLS-1$ + buffer.append(getClass().getName()) + .append("{additions [") //$NON-NLS-1$ + .append(getAdditions() != null ? getAdditions().toString() + : "null") //$NON-NLS-1$ .append("], removals [") //$NON-NLS-1$ - .append( - getRemovals() != null ? getRemovals().toString() - : "null") //$NON-NLS-1$ + .append(getRemovals() != null ? getRemovals().toString() + : "null") //$NON-NLS-1$ .append("]}"); //$NON-NLS-1$ return buffer.toString(); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/UnionSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/UnionSet.java index 533a9211..6463f9fe 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/UnionSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/UnionSet.java @@ -13,6 +13,7 @@ package org.eclipse.core.databinding.observable.set; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -20,6 +21,7 @@ import java.util.Iterator; import java.util.Set; import org.eclipse.core.databinding.observable.Diffs; +import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.internal.databinding.observable.IStalenessConsumer; import org.eclipse.core.internal.databinding.observable.StalenessTracker; @@ -35,14 +37,16 @@ import org.eclipse.core.internal.databinding.observable.StalenessTracker; * listeners may be invoked from any thread. * </p> * + * @param <E> + * type of the elements in the union set * @since 1.0 */ -public final class UnionSet extends ObservableSet { +public final class UnionSet<E> extends ObservableSet<E> { /** * child sets */ - private IObservableSet[] childSets; + private Set<IObservableSet<? extends E>> childSets; private boolean stale = false; @@ -51,15 +55,23 @@ public final class UnionSet extends ObservableSet { * when the first listener is added to the union set. Null if nobody is * listening to the UnionSet. */ - private HashMap refCounts = null; + private HashMap<E, Integer> refCounts = null; private StalenessTracker stalenessTracker; /** * @param childSets */ - public UnionSet(IObservableSet[] childSets) { - this(childSets, childSets[0].getElementType()); + public UnionSet(IObservableSet<? extends E>[] childSets) { + this(new HashSet<IObservableSet<? extends E>>(Arrays.asList(childSets))); + } + + /** + * @param childSets + * @since 1.5 + */ + public UnionSet(Set<IObservableSet<? extends E>> childSets) { + this(childSets, childSets.iterator().next().getElementType()); } /** @@ -67,19 +79,30 @@ public final class UnionSet extends ObservableSet { * @param elementType * @since 1.2 */ - public UnionSet(IObservableSet[] childSets, Object elementType) { - super(childSets[0].getRealm(), null, elementType); - System.arraycopy(childSets, 0, - this.childSets = new IObservableSet[childSets.length], 0, - childSets.length); - this.stalenessTracker = new StalenessTracker(childSets, - stalenessConsumer); + public UnionSet(IObservableSet<? extends E>[] childSets, Object elementType) { + this( + new HashSet<IObservableSet<? extends E>>( + Arrays.asList(childSets)), elementType); + } + + /** + * @param childSets + * @param elementType + * @since 1.5 + */ + public UnionSet(Set<IObservableSet<? extends E>> childSets, + Object elementType) { + super(childSets.iterator().next().getRealm(), null, elementType); + this.childSets = childSets; + + this.stalenessTracker = new StalenessTracker( + childSets.toArray(new IObservableSet[0]), stalenessConsumer); } - private ISetChangeListener childSetChangeListener = new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { - processAddsAndRemoves(event.diff.getAdditions(), event.diff - .getRemovals()); + private ISetChangeListener<E> childSetChangeListener = new ISetChangeListener<E>() { + public void handleSetChange(SetChangeEvent<E> event) { + processAddsAndRemoves(event.diff.getAdditions(), + event.diff.getRemovals()); } }; @@ -99,9 +122,7 @@ public final class UnionSet extends ObservableSet { return stale; } - for (int i = 0; i < childSets.length; i++) { - IObservableSet childSet = childSets[i]; - + for (IObservableSet<? extends E> childSet : childSets) { if (childSet.isStale()) { return true; } @@ -109,14 +130,15 @@ public final class UnionSet extends ObservableSet { return false; } - private void processAddsAndRemoves(Set adds, Set removes) { - Set addsToFire = new HashSet(); - Set removesToFire = new HashSet(); + private void processAddsAndRemoves(Set<? extends E> adds, + Set<? extends E> removes) { + Set<E> addsToFire = new HashSet<E>(); + Set<E> removesToFire = new HashSet<E>(); - for (Iterator iter = adds.iterator(); iter.hasNext();) { - Object added = iter.next(); + for (Iterator<? extends E> iter = adds.iterator(); iter.hasNext();) { + E added = iter.next(); - Integer refCount = (Integer) refCounts.get(added); + Integer refCount = refCounts.get(added); if (refCount == null) { refCounts.put(added, new Integer(1)); addsToFire.add(added); @@ -127,10 +149,10 @@ public final class UnionSet extends ObservableSet { } } - for (Iterator iter = removes.iterator(); iter.hasNext();) { - Object removed = iter.next(); + for (Iterator<? extends E> iter = removes.iterator(); iter.hasNext();) { + E removed = iter.next(); - Integer refCount = (Integer) refCounts.get(removed); + Integer refCount = refCounts.get(removed); if (refCount != null) { int refs = refCount.intValue(); if (refs <= 1) { @@ -154,37 +176,35 @@ public final class UnionSet extends ObservableSet { protected void firstListenerAdded() { super.firstListenerAdded(); - refCounts = new HashMap(); - for (int i = 0; i < childSets.length; i++) { - IObservableSet next = childSets[i]; - next.addSetChangeListener(childSetChangeListener); - incrementRefCounts(next); + refCounts = new HashMap<E, Integer>(); + for (IObservableSet<? extends E> childSet : childSets) { + childSet.addSetChangeListener(childSetChangeListener); + incrementRefCounts(childSet); } - stalenessTracker = new StalenessTracker(childSets, stalenessConsumer); + stalenessTracker = new StalenessTracker( + childSets.toArray(new IObservable[0]), stalenessConsumer); setWrappedSet(refCounts.keySet()); } protected void lastListenerRemoved() { super.lastListenerRemoved(); - for (int i = 0; i < childSets.length; i++) { - IObservableSet next = childSets[i]; - - next.removeSetChangeListener(childSetChangeListener); - stalenessTracker.removeObservable(next); + for (IObservableSet<? extends E> childSet : childSets) { + childSet.removeSetChangeListener(childSetChangeListener); + stalenessTracker.removeObservable(childSet); } refCounts = null; stalenessTracker = null; setWrappedSet(null); } - private ArrayList incrementRefCounts(Collection added) { - ArrayList adds = new ArrayList(); + private ArrayList<E> incrementRefCounts(Collection<? extends E> added) { + ArrayList<E> adds = new ArrayList<E>(); - for (Iterator iter = added.iterator(); iter.hasNext();) { - Object next = iter.next(); + for (Iterator<? extends E> iter = added.iterator(); iter.hasNext();) { + E next = iter.next(); - Integer refCount = (Integer) refCounts.get(next); + Integer refCount = refCounts.get(next); if (refCount == null) { adds.add(next); refCount = new Integer(1); @@ -205,12 +225,12 @@ public final class UnionSet extends ObservableSet { } } - private Set computeElements() { + private Set<E> computeElements() { // If there is no cached value, compute the union from scratch if (refCounts == null) { - Set result = new HashSet(); - for (int i = 0; i < childSets.length; i++) { - result.addAll(childSets[i]); + Set<E> result = new HashSet<E>(); + for (IObservableSet<? extends E> childSet : childSets) { + result.addAll(childSet); } return result; } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/WritableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/WritableSet.java index 52ded9dd..fe9f371e 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/WritableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/set/WritableSet.java @@ -31,9 +31,11 @@ import org.eclipse.core.databinding.observable.Realm; * listeners may be invoked from any thread. * </p> * + * @param <E> + * * @since 1.0 */ -public class WritableSet extends ObservableSet { +public class WritableSet<E> extends ObservableSet<E> { /** * Constructs a new empty instance in the default realm with a @@ -45,16 +47,16 @@ public class WritableSet extends ObservableSet { } /** - * Constructs a new instance in the default realm containing the - * elements of the given collection. Changes to the given collection after - * calling this method do not affect the contents of the created WritableSet. + * Constructs a new instance in the default realm containing the elements of + * the given collection. Changes to the given collection after calling this + * method do not affect the contents of the created WritableSet. * * @param c * @param elementType * can be <code>null</code> */ - public WritableSet(Collection c, Object elementType) { - this(Realm.getDefault(), new HashSet(c), elementType); + public WritableSet(Collection<? extends E> c, Object elementType) { + this(Realm.getDefault(), new HashSet<E>(c), elementType); } /** @@ -64,7 +66,7 @@ public class WritableSet extends ObservableSet { * @param realm */ public WritableSet(Realm realm) { - this(realm, new HashSet(), null); + this(realm, new HashSet<E>(), null); } /** @@ -78,32 +80,36 @@ public class WritableSet extends ObservableSet { * @param elementType * can be <code>null</code> */ - public WritableSet(Realm realm, Collection c, Object elementType) { - super(realm, new HashSet(c), elementType); + public WritableSet(Realm realm, Collection<? extends E> c, + Object elementType) { + super(realm, new HashSet<E>(c), elementType); this.elementType = elementType; } - public boolean add(Object o) { + public boolean add(E o) { getterCalled(); boolean added = wrappedSet.add(o); if (added) { - fireSetChange(Diffs.createSetDiff(Collections.singleton(o), Collections.EMPTY_SET)); + Set<E> removals = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(Collections.singleton(o), + removals)); } return added; } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { getterCalled(); - Set additions = new HashSet(); - Iterator it = c.iterator(); + Set<E> additions = new HashSet<E>(); + Iterator<? extends E> it = c.iterator(); while (it.hasNext()) { - Object element = it.next(); + E element = it.next(); if (wrappedSet.add(element)) { additions.add(element); } } if (additions.size() > 0) { - fireSetChange(Diffs.createSetDiff(additions, Collections.EMPTY_SET)); + Set<E> removals = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, removals)); return true; } return false; @@ -113,42 +119,45 @@ public class WritableSet extends ObservableSet { getterCalled(); boolean removed = wrappedSet.remove(o); if (removed) { - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, Collections - .singleton(o))); + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, + Collections.singleton((E) o))); } return removed; } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { getterCalled(); - Set removes = new HashSet(); - Iterator it = c.iterator(); + Set<E> removes = new HashSet<E>(); + Iterator<?> it = c.iterator(); while (it.hasNext()) { Object element = it.next(); if (wrappedSet.remove(element)) { - removes.add(element); + removes.add((E) element); } } if (removes.size() > 0) { - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removes)); + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, removes)); return true; } return false; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { getterCalled(); - Set removes = new HashSet(); - Iterator it = wrappedSet.iterator(); + Set<E> removes = new HashSet<E>(); + Iterator<E> it = wrappedSet.iterator(); while (it.hasNext()) { - Object element = it.next(); + E element = it.next(); if (!c.contains(element)) { it.remove(); removes.add(element); } } if (removes.size() > 0) { - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removes)); + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, removes)); return true; } return false; @@ -156,16 +165,19 @@ public class WritableSet extends ObservableSet { public void clear() { getterCalled(); - Set removes = new HashSet(wrappedSet); + Set<E> removes = new HashSet<E>(wrappedSet); + Set<E> additions = Collections.emptySet(); wrappedSet.clear(); - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removes)); + fireSetChange(Diffs.createSetDiff(additions, removes)); } /** - * @param elementType can be <code>null</code> + * @param elementType + * can be <code>null</code> * @return new instance with the default realm */ - public static WritableSet withElementType(Object elementType) { - return new WritableSet(Realm.getDefault(), new HashSet(), elementType); + public static WritableSet<?> withElementType(Object elementType) { + return new WritableSet<Object>(Realm.getDefault(), + new HashSet<Object>(), elementType); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractObservableValue.java index 512dc3b6..96766fc5 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractObservableValue.java @@ -24,10 +24,13 @@ import org.eclipse.core.databinding.observable.Realm; * the {@link Realm#isCurrent() current realm}. Methods for adding and removing * listeners may be invoked from any thread. * </p> + * + * @param <T> * @since 1.0 * */ -abstract public class AbstractObservableValue extends AbstractObservable implements IObservableValue { +abstract public class AbstractObservableValue<T> extends AbstractObservable + implements IObservableValue<T> { /** * Constructs a new instance with the default realm. */ @@ -42,15 +45,17 @@ abstract public class AbstractObservableValue extends AbstractObservable impleme super(realm); } - public synchronized void addValueChangeListener(IValueChangeListener listener) { + public synchronized void addValueChangeListener( + IValueChangeListener<T> listener) { addListener(ValueChangeEvent.TYPE, listener); } - public synchronized void removeValueChangeListener(IValueChangeListener listener) { + public synchronized void removeValueChangeListener( + IValueChangeListener<T> listener) { removeListener(ValueChangeEvent.TYPE, listener); } - final public void setValue(Object value) { + final public void setValue(T value) { checkRealm(); doSetValue(value); } @@ -61,22 +66,22 @@ abstract public class AbstractObservableValue extends AbstractObservable impleme * * @param value */ - protected void doSetValue(Object value) { + protected void doSetValue(T value) { throw new UnsupportedOperationException(); } - protected void fireValueChange(ValueDiff diff) { + protected void fireValueChange(ValueDiff<T> diff) { // fire general change event first super.fireChange(); - fireEvent(new ValueChangeEvent(this, diff)); + fireEvent(new ValueChangeEvent<T>(this, diff)); } - public final Object getValue() { + public final T getValue() { getterCalled(); return doGetValue(); } - abstract protected Object doGetValue(); + abstract protected T doGetValue(); public boolean isStale() { getterCalled(); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractVetoableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractVetoableValue.java index 1e99e1c5..e31f61bc 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractVetoableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/AbstractVetoableValue.java @@ -23,11 +23,13 @@ import org.eclipse.core.internal.databinding.observable.Util; * the {@link Realm#isCurrent() current realm}. Methods for adding and removing * listeners may be invoked from any thread. * </p> + * + * @param <T> * @since 1.0 * */ -public abstract class AbstractVetoableValue extends AbstractObservableValue - implements IVetoableValue { +public abstract class AbstractVetoableValue<T> extends + AbstractObservableValue<T> implements IVetoableValue<T> { /** * Creates a new vetoable value. @@ -43,34 +45,35 @@ public abstract class AbstractVetoableValue extends AbstractObservableValue super(realm); } - final protected void doSetValue(Object value) { - Object currentValue = doGetValue(); - ValueDiff diff = Diffs.createValueDiff(currentValue, value); + final protected void doSetValue(T value) { + T currentValue = doGetValue(); + ValueDiff<T> diff = Diffs.createValueDiff(currentValue, value); boolean okToProceed = fireValueChanging(diff); if (!okToProceed) { throw new ChangeVetoException("Change not permitted"); //$NON-NLS-1$ } doSetApprovedValue(value); - + if (!Util.equals(diff.getOldValue(), diff.getNewValue())) { fireValueChange(diff); } } /** - * Sets the value. Invoked after performing veto checks. Should not fire change events. + * Sets the value. Invoked after performing veto checks. Should not fire + * change events. * * @param value */ - protected abstract void doSetApprovedValue(Object value); + protected abstract void doSetApprovedValue(T value); public synchronized void addValueChangingListener( - IValueChangingListener listener) { + IValueChangingListener<T> listener) { addListener(ValueChangingEvent.TYPE, listener); } public synchronized void removeValueChangingListener( - IValueChangingListener listener) { + IValueChangingListener<T> listener) { removeListener(ValueChangingEvent.TYPE, listener); } @@ -81,10 +84,10 @@ public abstract class AbstractVetoableValue extends AbstractObservableValue * @param diff * @return false if the change was vetoed, true otherwise */ - protected boolean fireValueChanging(ValueDiff diff) { + protected boolean fireValueChanging(ValueDiff<T> diff) { checkRealm(); - ValueChangingEvent event = new ValueChangingEvent(this, diff); + ValueChangingEvent<T> event = new ValueChangingEvent<T>(this, diff); fireEvent(event); return !event.veto; } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ComputedValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ComputedValue.java index cbe909ef..bd405f36 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ComputedValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ComputedValue.java @@ -59,15 +59,17 @@ import org.eclipse.core.databinding.observable.list.IObservableList; * System.out.println(sum.getValue()); // => 13 * </pre> * + * @param <T> + * * @since 1.0 */ -public abstract class ComputedValue extends AbstractObservableValue { +public abstract class ComputedValue<T> extends AbstractObservableValue<T> { private boolean dirty = true; private boolean stale = false; - private Object cachedValue = null; + private T cachedValue = null; /** * Array of observables this computed value depends on. This field has a @@ -128,36 +130,41 @@ public abstract class ComputedValue extends AbstractObservableValue { * </p> * */ - private class PrivateInterface implements Runnable, IChangeListener, - IStaleListener { - public void run() { - cachedValue = calculate(); + private class PrivateChangeInterface implements IChangeListener { + public void handleChange(ChangeEvent event) { + makeDirty(); } + } + private class PrivateStaleInterface implements IStaleListener { public void handleStale(StaleEvent event) { if (!dirty && !stale) { stale = true; fireStale(); } } + } - public void handleChange(ChangeEvent event) { - makeDirty(); + private class PrivateRunnableInterface implements Runnable { + public void run() { + cachedValue = calculate(); } } - private PrivateInterface privateInterface = new PrivateInterface(); + private IChangeListener privateChangeInterface = new PrivateChangeInterface(); + private IStaleListener privateStaleInterface = new PrivateStaleInterface(); + private Runnable privateRunnableInterface = new PrivateRunnableInterface(); private Object valueType; - protected final Object doGetValue() { + protected final T doGetValue() { if (dirty) { // This line will do the following: // - Run the calculate method // - While doing so, add any observable that is touched to the // dependencies list IObservable[] newDependencies = ObservableTracker.runAndMonitor( - privateInterface, privateInterface, null); + privateRunnableInterface, privateChangeInterface, null); stale = false; for (int i = 0; i < newDependencies.length; i++) { @@ -166,7 +173,7 @@ public abstract class ComputedValue extends AbstractObservableValue { if (observable.isStale()) { stale = true; } else { - observable.addStaleListener(privateInterface); + observable.addStaleListener(privateStaleInterface); } } @@ -186,7 +193,7 @@ public abstract class ComputedValue extends AbstractObservableValue { * * @return the object's value */ - protected abstract Object calculate(); + protected abstract T calculate(); protected final void makeDirty() { if (!dirty) { @@ -195,16 +202,16 @@ public abstract class ComputedValue extends AbstractObservableValue { stopListening(); // copy the old value - final Object oldValue = cachedValue; + final T oldValue = cachedValue; // Fire the "dirty" event. This implementation recomputes the new // value lazily. - fireValueChange(new ValueDiff() { + fireValueChange(new ValueDiff<T>() { - public Object getOldValue() { + public T getOldValue() { return oldValue; } - public Object getNewValue() { + public T getNewValue() { return getValue(); } }); @@ -220,8 +227,8 @@ public abstract class ComputedValue extends AbstractObservableValue { for (int i = 0; i < dependencies.length; i++) { IObservable observable = dependencies[i]; - observable.removeChangeListener(privateInterface); - observable.removeStaleListener(privateInterface); + observable.removeChangeListener(privateChangeInterface); + observable.removeStaleListener(privateStaleInterface); } dependencies = null; } @@ -278,7 +285,7 @@ public abstract class ComputedValue extends AbstractObservableValue { } public synchronized void addValueChangeListener( - IValueChangeListener listener) { + IValueChangeListener<T> listener) { super.addValueChangeListener(listener); // If somebody is listening, we need to make sure we attach our own // listeners diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DateAndTimeObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DateAndTimeObservableValue.java index b2d0d3fb..8e20a486 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DateAndTimeObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DateAndTimeObservableValue.java @@ -84,33 +84,38 @@ import org.eclipse.core.runtime.Assert; * * @since 1.2 */ -public class DateAndTimeObservableValue extends AbstractObservableValue { - private IObservableValue dateObservable; - private IObservableValue timeObservable; - private PrivateInterface privateInterface; - private Object cachedValue; +public class DateAndTimeObservableValue extends AbstractObservableValue<Date> { + private IObservableValue<Date> dateObservable; + private IObservableValue<Date> timeObservable; + private PrivateChangeInterface privateChangeInterface; + private PrivateStaleInterface privateStaleInterface; + private PrivateDisposeInterface privateDisposeInterface; + private Date cachedValue; private boolean updating; - private class PrivateInterface implements IChangeListener, IStaleListener, - IDisposeListener { - public void handleDispose(DisposeEvent staleEvent) { - dispose(); - } - + private class PrivateChangeInterface implements IChangeListener { public void handleChange(ChangeEvent event) { if (!isDisposed() && !updating) notifyIfChanged(); } + } + private class PrivateStaleInterface implements IStaleListener { public void handleStale(StaleEvent staleEvent) { if (!isDisposed()) fireStale(); } } + private class PrivateDisposeInterface implements IDisposeListener { + public void handleDispose(DisposeEvent staleEvent) { + dispose(); + } + } + // One calendar per thread to preserve thread-safety - private static final ThreadLocal calendar = new ThreadLocal() { - protected Object initialValue() { + private static final ThreadLocal<Calendar> calendar = new ThreadLocal<Calendar>() { + protected Calendar initialValue() { return Calendar.getInstance(); } }; @@ -126,8 +131,8 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { * the observable used for the time component (hour, minute, * second and millisecond) of the constructed observable. */ - public DateAndTimeObservableValue(IObservableValue dateObservable, - IObservableValue timeObservable) { + public DateAndTimeObservableValue(IObservableValue<Date> dateObservable, + IObservableValue<Date> timeObservable) { super(dateObservable.getRealm()); this.dateObservable = dateObservable; this.timeObservable = timeObservable; @@ -135,9 +140,12 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { Assert.isTrue(dateObservable.getRealm().equals( timeObservable.getRealm())); - privateInterface = new PrivateInterface(); - dateObservable.addDisposeListener(privateInterface); - timeObservable.addDisposeListener(privateInterface); + privateChangeInterface = new PrivateChangeInterface(); + privateStaleInterface = new PrivateStaleInterface(); + privateDisposeInterface = new PrivateDisposeInterface(); + + dateObservable.addDisposeListener(privateDisposeInterface); + timeObservable.addDisposeListener(privateDisposeInterface); } public Object getValueType() { @@ -147,22 +155,22 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { protected void firstListenerAdded() { cachedValue = doGetValue(); - dateObservable.addChangeListener(privateInterface); - dateObservable.addStaleListener(privateInterface); + dateObservable.addChangeListener(privateChangeInterface); + dateObservable.addStaleListener(privateStaleInterface); - timeObservable.addChangeListener(privateInterface); - timeObservable.addStaleListener(privateInterface); + timeObservable.addChangeListener(privateChangeInterface); + timeObservable.addStaleListener(privateStaleInterface); } protected void lastListenerRemoved() { if (dateObservable != null && !dateObservable.isDisposed()) { - dateObservable.removeChangeListener(privateInterface); - dateObservable.removeStaleListener(privateInterface); + dateObservable.removeChangeListener(privateChangeInterface); + dateObservable.removeStaleListener(privateStaleInterface); } if (timeObservable != null && !timeObservable.isDisposed()) { - timeObservable.removeChangeListener(privateInterface); - timeObservable.removeStaleListener(privateInterface); + timeObservable.removeChangeListener(privateChangeInterface); + timeObservable.removeStaleListener(privateStaleInterface); } cachedValue = null; @@ -170,21 +178,24 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { private void notifyIfChanged() { if (hasListeners()) { - Object oldValue = cachedValue; - Object newValue = cachedValue = doGetValue(); + Date oldValue = cachedValue; + Date newValue = cachedValue = doGetValue(); if (!Util.equals(oldValue, newValue)) fireValueChange(Diffs.createValueDiff(oldValue, newValue)); } } - protected Object doGetValue() { - Date dateValue = (Date) dateObservable.getValue(); + /** + * @since 1.5 + */ + protected Date doGetValue() { + Date dateValue = dateObservable.getValue(); if (dateValue == null) return null; - Date timeValue = (Date) timeObservable.getValue(); + Date timeValue = timeObservable.getValue(); - Calendar cal = (Calendar) calendar.get(); + Calendar cal = calendar.get(); cal.setTime(dateValue); int year = cal.get(Calendar.YEAR); @@ -206,17 +217,18 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { return cal.getTime(); } - protected void doSetValue(Object value) { - Date date = (Date) value; - + /** + * @since 1.5 + */ + protected void doSetValue(Date combinedDate) { Date dateValue; Date timeValue; - Calendar cal = (Calendar) calendar.get(); - if (date == null) + Calendar cal = calendar.get(); + if (combinedDate == null) cal.clear(); else - cal.setTime(date); + cal.setTime(combinedDate); int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH); @@ -226,10 +238,10 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { int second = cal.get(Calendar.SECOND); int millis = cal.get(Calendar.MILLISECOND); - if (date == null) { + if (combinedDate == null) { dateValue = null; } else { - dateValue = (Date) dateObservable.getValue(); + dateValue = dateObservable.getValue(); if (dateValue == null) cal.clear(); else @@ -240,7 +252,7 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { dateValue = cal.getTime(); } - timeValue = (Date) timeObservable.getValue(); + timeValue = timeObservable.getValue(); if (timeValue == null) cal.clear(); else @@ -271,18 +283,20 @@ public class DateAndTimeObservableValue extends AbstractObservableValue { checkRealm(); if (!isDisposed()) { if (!dateObservable.isDisposed()) { - dateObservable.removeDisposeListener(privateInterface); - dateObservable.removeChangeListener(privateInterface); - dateObservable.removeStaleListener(privateInterface); + dateObservable.removeDisposeListener(privateDisposeInterface); + dateObservable.removeChangeListener(privateChangeInterface); + dateObservable.removeStaleListener(privateStaleInterface); } if (!timeObservable.isDisposed()) { - timeObservable.removeDisposeListener(privateInterface); - timeObservable.removeChangeListener(privateInterface); - timeObservable.removeStaleListener(privateInterface); + timeObservable.removeDisposeListener(privateDisposeInterface); + timeObservable.removeChangeListener(privateChangeInterface); + timeObservable.removeStaleListener(privateStaleInterface); } dateObservable = null; timeObservable = null; - privateInterface = null; + privateChangeInterface = null; + privateStaleInterface = null; + privateDisposeInterface = null; cachedValue = null; } super.dispose(); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingObservableValue.java index 6ab290fb..154d66d4 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingObservableValue.java @@ -17,13 +17,15 @@ import org.eclipse.core.databinding.observable.DecoratingObservable; /** * An observable value which decorates another observable value. * + * @param <T> + * * @since 1.2 */ -public class DecoratingObservableValue extends DecoratingObservable implements - IObservableValue { - private IObservableValue decorated; +public class DecoratingObservableValue<T> extends DecoratingObservable + implements IObservableValue<T> { + private IObservableValue<T> decorated; - private IValueChangeListener valueChangeListener; + private IValueChangeListener<T> valueChangeListener; /** * Constructs a DecoratingObservableValue which decorates the given @@ -31,28 +33,28 @@ public class DecoratingObservableValue extends DecoratingObservable implements * * @param decorated * the observable value being decorated - * @param disposeDecoratedOnDispose + * @param disposeDecoratedOnDispose */ - public DecoratingObservableValue(IObservableValue decorated, + public DecoratingObservableValue(IObservableValue<T> decorated, boolean disposeDecoratedOnDispose) { super(decorated, disposeDecoratedOnDispose); this.decorated = decorated; } public synchronized void addValueChangeListener( - IValueChangeListener listener) { + IValueChangeListener<T> listener) { addListener(ValueChangeEvent.TYPE, listener); } public synchronized void removeValueChangeListener( - IValueChangeListener listener) { + IValueChangeListener<T> listener) { removeListener(ValueChangeEvent.TYPE, listener); } - protected void fireValueChange(ValueDiff diff) { + protected void fireValueChange(ValueDiff<T> diff) { // fire general change event first super.fireChange(); - fireEvent(new ValueChangeEvent(this, diff)); + fireEvent(new ValueChangeEvent<T>(this, diff)); } protected void fireChange() { @@ -62,8 +64,8 @@ public class DecoratingObservableValue extends DecoratingObservable implements protected void firstListenerAdded() { if (valueChangeListener == null) { - valueChangeListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + valueChangeListener = new IValueChangeListener<T>() { + public void handleValueChange(ValueChangeEvent<T> event) { DecoratingObservableValue.this.handleValueChange(event); } }; @@ -89,16 +91,16 @@ public class DecoratingObservableValue extends DecoratingObservable implements * @param event * the change event received from the decorated observable */ - protected void handleValueChange(final ValueChangeEvent event) { + protected void handleValueChange(final ValueChangeEvent<T> event) { fireValueChange(event.diff); } - public Object getValue() { + public T getValue() { getterCalled(); return decorated.getValue(); } - public void setValue(Object value) { + public void setValue(T value) { checkRealm(); decorated.setValue(value); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingVetoableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingVetoableValue.java index 0d7108fd..73b64eed 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingVetoableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DecoratingVetoableValue.java @@ -16,23 +16,24 @@ import org.eclipse.core.databinding.observable.Diffs; /** * An {@link IVetoableValue} decorator for an observable value. * + * @param <T> * @since 1.2 */ -public class DecoratingVetoableValue extends DecoratingObservableValue - implements IVetoableValue { +public class DecoratingVetoableValue<T> extends DecoratingObservableValue<T> + implements IVetoableValue<T> { /** * @param decorated * @param disposeDecoratedOnDispose */ - public DecoratingVetoableValue(IObservableValue decorated, + public DecoratingVetoableValue(IObservableValue<T> decorated, boolean disposeDecoratedOnDispose) { super(decorated, disposeDecoratedOnDispose); } - public void setValue(Object value) { + public void setValue(T value) { checkRealm(); - Object currentValue = getValue(); - ValueDiff diff = Diffs.createValueDiff(currentValue, value); + T currentValue = getValue(); + ValueDiff<T> diff = Diffs.createValueDiff(currentValue, value); boolean okToProceed = fireValueChanging(diff); if (!okToProceed) { throw new ChangeVetoException("Change not permitted"); //$NON-NLS-1$ @@ -41,12 +42,12 @@ public class DecoratingVetoableValue extends DecoratingObservableValue } public synchronized void addValueChangingListener( - IValueChangingListener listener) { + IValueChangingListener<T> listener) { addListener(ValueChangingEvent.TYPE, listener); } public synchronized void removeValueChangingListener( - IValueChangingListener listener) { + IValueChangingListener<T> listener) { removeListener(ValueChangingEvent.TYPE, listener); } @@ -57,10 +58,10 @@ public class DecoratingVetoableValue extends DecoratingObservableValue * @param diff * @return false if the change was vetoed, true otherwise */ - protected boolean fireValueChanging(ValueDiff diff) { + protected boolean fireValueChanging(ValueDiff<T> diff) { checkRealm(); - ValueChangingEvent event = new ValueChangingEvent(this, diff); + ValueChangingEvent<T> event = new ValueChangingEvent<T>(this, diff); fireEvent(event); return !event.veto; } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java index 4d5ffaf6..346051b2 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/DuplexingObservableValue.java @@ -23,32 +23,36 @@ import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.internal.databinding.observable.Util; /** + * @param <T> * @since 1.2 */ -public abstract class DuplexingObservableValue extends AbstractObservableValue { +public abstract class DuplexingObservableValue<T> extends + AbstractObservableValue<T> { /** * Returns a DuplexingObservableValue implementation with predefined values * to use if the list is empty or contains multiple different values. * + * @param <T> + * * @param target * the observable list * @param emptyValue * the value to use when the target list is empty * @param multiValue * the value to use when the target list contains multiple values - * that are not equivalent to eachother. + * that are not equivalent to each other. * @return a DuplexingObservableValue implementation with predefined values * to use if the list is empty or contains multiple different * values. */ - public static DuplexingObservableValue withDefaults(IObservableList target, - final Object emptyValue, final Object multiValue) { - return new DuplexingObservableValue(target) { - protected Object coalesceElements(Collection elements) { + public static <T> DuplexingObservableValue<T> withDefaults( + IObservableList<T> target, final T emptyValue, final T multiValue) { + return new DuplexingObservableValue<T>(target) { + protected T coalesceElements(Collection<T> elements) { if (elements.isEmpty()) return emptyValue; - Iterator it = elements.iterator(); - Object first = it.next(); + Iterator<T> it = elements.iterator(); + T first = it.next(); while (it.hasNext()) if (!Util.equals(first, it.next())) return multiValue; @@ -57,19 +61,20 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { }; } - private IObservableList target; + private IObservableList<T> target; private final Object valueType; private boolean dirty = true; private boolean updating = false; - private Object cachedValue = null; // applicable only while hasListener() + private T cachedValue = null; // applicable only while hasListener() - private PrivateInterface privateInterface; + private IChangeListener privateChangeInterface; + private IStaleListener privateStaleInterface; /** * @param target */ - public DuplexingObservableValue(IObservableList target) { + public DuplexingObservableValue(IObservableList<T> target) { this(target, target.getElementType()); } @@ -77,18 +82,20 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { * @param target * @param valueType */ - public DuplexingObservableValue(IObservableList target, Object valueType) { + public DuplexingObservableValue(IObservableList<T> target, Object valueType) { super(target.getRealm()); this.target = target; this.valueType = valueType; } - private class PrivateInterface implements IChangeListener, IStaleListener { + private class PrivateChangeInterface implements IChangeListener { public void handleChange(ChangeEvent event) { if (!updating) makeDirty(); } + } + private class PrivateStaleInterface implements IStaleListener { public void handleStale(StaleEvent staleEvent) { if (!dirty) { fireStale(); @@ -97,15 +104,17 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { } protected void firstListenerAdded() { - if (privateInterface == null) - privateInterface = new PrivateInterface(); - target.addChangeListener(privateInterface); - target.addStaleListener(privateInterface); + if (privateChangeInterface == null) + privateChangeInterface = new PrivateChangeInterface(); + if (privateStaleInterface == null) + privateStaleInterface = new PrivateStaleInterface(); + target.addChangeListener(privateChangeInterface); + target.addStaleListener(privateStaleInterface); } protected void lastListenerRemoved() { - target.removeChangeListener(privateInterface); - target.removeStaleListener(privateInterface); + target.removeChangeListener(privateChangeInterface); + target.removeStaleListener(privateStaleInterface); } protected final void makeDirty() { @@ -113,15 +122,15 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { dirty = true; // copy the old value - final Object oldValue = cachedValue; + final T oldValue = cachedValue; // Fire the "dirty" event. This implementation recomputes the new // value lazily. - fireValueChange(new ValueDiff() { - public Object getOldValue() { + fireValueChange(new ValueDiff<T>() { + public T getOldValue() { return oldValue; } - public Object getNewValue() { + public T getNewValue() { return getValue(); } }); @@ -133,7 +142,7 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { return target.isStale(); } - protected Object doGetValue() { + protected T doGetValue() { if (!hasListeners()) return coalesceElements(target); @@ -147,10 +156,10 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { return cachedValue; } - protected abstract Object coalesceElements(Collection elements); + protected abstract T coalesceElements(Collection<T> elements); - protected void doSetValue(Object value) { - final Object oldValue = cachedValue; + protected void doSetValue(T value) { + final T oldValue = cachedValue; boolean wasUpdating = updating; try { @@ -164,12 +173,12 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { // Fire the "dirty" event. This implementation recomputes the new // value lazily. if (hasListeners()) { - fireValueChange(new ValueDiff() { - public Object getOldValue() { + fireValueChange(new ValueDiff<T>() { + public T getOldValue() { return oldValue; } - public Object getNewValue() { + public T getNewValue() { return getValue(); } }); @@ -188,7 +197,7 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { } public synchronized void addValueChangeListener( - IValueChangeListener listener) { + IValueChangeListener<T> listener) { super.addValueChangeListener(listener); // If somebody is listening, we need to make sure we attach our own // listeners @@ -219,12 +228,15 @@ public abstract class DuplexingObservableValue extends AbstractObservableValue { } public synchronized void dispose() { - if (privateInterface != null && target != null) { - target.removeChangeListener(privateInterface); - target.removeStaleListener(privateInterface); + if (privateChangeInterface != null && target != null) { + target.removeChangeListener(privateChangeInterface); + } + if (privateStaleInterface != null && target != null) { + target.removeStaleListener(privateStaleInterface); } target = null; - privateInterface = null; + privateChangeInterface = null; + privateStaleInterface = null; super.dispose(); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IObservableValue.java index 820fa930..11a1064e 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IObservableValue.java @@ -18,6 +18,8 @@ import org.eclipse.core.databinding.observable.Realm; /** * A value whose changes can be tracked by value change listeners. * + * @param <T> + * * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that * implement this interface. Note that direct implementers of this @@ -28,7 +30,7 @@ import org.eclipse.core.databinding.observable.Realm; * * @since 1.0 */ -public interface IObservableValue extends IObservable { +public interface IObservableValue<T> extends IObservable { /** * The value type of this observable value, or <code>null</code> if this @@ -39,31 +41,32 @@ public interface IObservableValue extends IObservable { public Object getValueType(); /** - * Returns the value. Must be invoked in the {@link Realm} of the observable. + * Returns the value. Must be invoked in the {@link Realm} of the + * observable. * * @return the current value * @TrackedGetter */ - public Object getValue(); + public T getValue(); /** - * Sets the value. Must be invoked in the {@link Realm} of the observable. + * Sets the value. Must be invoked in the {@link Realm} of the observable. * * @param value * the value to set * @throws UnsupportedOperationException * if this observable value cannot be set. */ - public void setValue(Object value); + public void setValue(T value); /** * * @param listener */ - public void addValueChangeListener(IValueChangeListener listener); + public void addValueChangeListener(IValueChangeListener<T> listener); /** * @param listener */ - public void removeValueChangeListener(IValueChangeListener listener); + public void removeValueChangeListener(IValueChangeListener<T> listener); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangeListener.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangeListener.java index 7af53822..b1ef6ce2 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangeListener.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangeListener.java @@ -16,10 +16,12 @@ import org.eclipse.core.databinding.observable.IObservablesListener; /** * Listener for changes to observable values. * + * @param <T> + * * @since 1.0 * */ -public interface IValueChangeListener extends IObservablesListener { +public interface IValueChangeListener<T> extends IObservablesListener { /** * Handles a change to an observable value. The given event object must only @@ -30,6 +32,6 @@ public interface IValueChangeListener extends IObservablesListener { * @param event * the event */ - void handleValueChange(ValueChangeEvent event); + void handleValueChange(ValueChangeEvent<T> event); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangingListener.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangingListener.java index ceb07b74..c1883972 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangingListener.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IValueChangingListener.java @@ -15,10 +15,12 @@ import org.eclipse.core.databinding.observable.IObservablesListener; /** * Listener for pre-change events for observable values. * + * @param <T> + * * @since 1.0 * */ -public interface IValueChangingListener extends IObservablesListener { +public interface IValueChangingListener<T> extends IObservablesListener { /** * This method is called when the value is about to change and provides an @@ -29,6 +31,6 @@ public interface IValueChangingListener extends IObservablesListener { * * @param event */ - public void handleValueChanging(ValueChangingEvent event); + public void handleValueChanging(ValueChangingEvent<T> event); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IVetoableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IVetoableValue.java index 1b795eda..aa0a0e1b 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IVetoableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/IVetoableValue.java @@ -13,6 +13,8 @@ package org.eclipse.core.databinding.observable.value; /** * An observable value whose changes can be vetoed by listeners. * + * @param <T> + * * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that @@ -23,16 +25,16 @@ package org.eclipse.core.databinding.observable.value; * @since 1.0 * */ -public interface IVetoableValue extends IObservableValue { - +public interface IVetoableValue<T> extends IObservableValue<T> { + /** * @param listener */ - public void addValueChangingListener(IValueChangingListener listener); - + public void addValueChangingListener(IValueChangingListener<T> listener); + /** * @param listener */ - public void removeValueChangingListener(IValueChangingListener listener); + public void removeValueChangingListener(IValueChangingListener<T> listener); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/SelectObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/SelectObservableValue.java index 12dbe1e2..e3e4b724 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/SelectObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/SelectObservableValue.java @@ -11,6 +11,9 @@ package org.eclipse.core.databinding.observable.value; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.internal.databinding.observable.Util; @@ -23,16 +26,18 @@ import org.eclipse.core.internal.databinding.observable.Util; * observable has a value of Boolean.TRUE, or null if none of the observable's * values are Boolean.TRUE. * + * @param <T> + * * @noextend This class is not intended to be subclassed by clients. * * @since 1.2 */ -public class SelectObservableValue extends AbstractObservableValue { +public class SelectObservableValue<T> extends AbstractObservableValue<T> { private class Option { - private final Object value; - private final IObservableValue observable; + private final T value; + private final IObservableValue<Boolean> observable; - public Option(Object value, IObservableValue observable) { + public Option(T value, IObservableValue<Boolean> observable) { this.value = value; this.observable = observable; } @@ -40,15 +45,16 @@ public class SelectObservableValue extends AbstractObservableValue { private final Object valueType; - private Option[] options; + private List<Option> options; private int selectionIndex = -1; // n/a while not hasListeners() private boolean updating = false; - private IValueChangeListener listener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + private IValueChangeListener<Boolean> listener = new IValueChangeListener<Boolean>() { + public void handleValueChange(ValueChangeEvent<Boolean> event) { if (!updating) { - IObservableValue observable = event.getObservableValue(); + IObservableValue<Boolean> observable = event + .getObservableValue(); if (Boolean.TRUE.equals(observable.getValue())) { notifyIfChanged(indexOfObservable(observable)); } @@ -96,20 +102,20 @@ public class SelectObservableValue extends AbstractObservableValue { public SelectObservableValue(Realm realm, Object valueType) { super(realm); this.valueType = valueType; - this.options = new Option[0]; + this.options = new ArrayList<Option>(); } protected void firstListenerAdded() { super.firstListenerAdded(); selectionIndex = indexOfValue(getLiveValue()); - for (int i = 0; i < options.length; i++) { - options[i].observable.addValueChangeListener(listener); + for (Option option : options) { + option.observable.addValueChangeListener(listener); } } protected void lastListenerRemoved() { - for (int i = 0; i < options.length; i++) { - options[i].observable.removeValueChangeListener(listener); + for (Option option : options) { + option.observable.removeValueChangeListener(listener); } selectionIndex = -1; super.lastListenerRemoved(); @@ -121,8 +127,8 @@ public class SelectObservableValue extends AbstractObservableValue { private void notifyIfChanged(int index) { if (hasListeners() && selectionIndex != index) { - Object oldValue = valueAtIndex(selectionIndex); - Object newValue = valueAtIndex(index); + T oldValue = valueAtIndex(selectionIndex); + T newValue = valueAtIndex(index); selectionIndex = index; fireValueChange(Diffs.createValueDiff(oldValue, newValue)); } @@ -137,11 +143,11 @@ public class SelectObservableValue extends AbstractObservableValue { * @param observable * an observable of value type Boolean.class or Boolean.TYPE */ - public void addOption(Object value, IObservableValue observable) { + public void addOption(T value, IObservableValue<Boolean> observable) { checkRealm(); Option option = new Option(value, observable); - addOption(option); + options.add(option); if (hasListeners()) { observable.addValueChangeListener(listener); @@ -151,21 +157,14 @@ public class SelectObservableValue extends AbstractObservableValue { } } - private void addOption(Option option) { - Option[] newOptions = new Option[options.length + 1]; - System.arraycopy(options, 0, newOptions, 0, options.length); - newOptions[options.length] = option; - options = newOptions; - } - - protected Object doGetValue() { + protected T doGetValue() { return hasListeners() ? valueAtIndex(selectionIndex) : getLiveValue(); } - private Object getLiveValue() { - for (int i = 0; i < options.length; i++) { - if (Boolean.TRUE.equals(options[i].observable.getValue())) - return options[i].value; + private T getLiveValue() { + for (Option option : options) { + if (Boolean.TRUE.equals(option.observable.getValue())) + return option.value; } return null; } @@ -175,8 +174,8 @@ public class SelectObservableValue extends AbstractObservableValue { try { updating = true; - for (int i = 0; i < options.length; i++) { - options[i].observable.setValue(i == index ? Boolean.TRUE + for (int i = 0; i < options.size(); i++) { + options.get(i).observable.setValue(i == index ? Boolean.TRUE : Boolean.FALSE); } } finally { @@ -186,22 +185,22 @@ public class SelectObservableValue extends AbstractObservableValue { notifyIfChanged(index); } - private Object valueAtIndex(int index) { + private T valueAtIndex(int index) { if (index == -1) return null; - return options[index].value; + return options.get(index).value; } private int indexOfValue(Object value) { - for (int i = 0; i < options.length; i++) - if (Util.equals(options[i].value, value)) + for (int i = 0; i < options.size(); i++) + if (Util.equals(options.get(i).value, value)) return i; return -1; } - private int indexOfObservable(IObservableValue observable) { - for (int i = 0; i < options.length; i++) - if (options[i].observable == observable) + private int indexOfObservable(IObservableValue<Boolean> observable) { + for (int i = 0; i < options.size(); i++) + if (options.get(i).observable == observable) return i; return -1; } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangeEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangeEvent.java index 3d4fba90..99b0b3dd 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangeEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangeEvent.java @@ -15,13 +15,15 @@ import org.eclipse.core.databinding.observable.IObservablesListener; import org.eclipse.core.databinding.observable.ObservableEvent; /** - * Value change event describing a change of an {@link IObservableValue} + * Value change event describing a change of an {@link IObservableValue} * object's current value. * + * @param <T> + * * @since 1.0 * */ -public class ValueChangeEvent extends ObservableEvent { +public class ValueChangeEvent<T> extends ObservableEvent<ValueChangeEvent<T>> { /** * @@ -34,7 +36,13 @@ public class ValueChangeEvent extends ObservableEvent { * Description of the change to the source observable value. Listeners must * not change this field. */ - public ValueDiff diff; + public ValueDiff<T> diff; + + /** + * Always identical to <code>EventObject.source</code> but the type + * information is maintained. + */ + private IObservableValue<T> typedSource; /** * Creates a new value change event. @@ -44,8 +52,9 @@ public class ValueChangeEvent extends ObservableEvent { * @param diff * the value change */ - public ValueChangeEvent(IObservableValue source, ValueDiff diff) { + public ValueChangeEvent(IObservableValue<T> source, ValueDiff<T> diff) { super(source); + this.typedSource = source; this.diff = diff; } @@ -54,12 +63,12 @@ public class ValueChangeEvent extends ObservableEvent { * * @return returns the observable value from which this event originated */ - public IObservableValue getObservableValue() { - return (IObservableValue) source; + public IObservableValue<T> getObservableValue() { + return typedSource; } protected void dispatch(IObservablesListener listener) { - ((IValueChangeListener) listener).handleValueChange(this); + ((IValueChangeListener<T>) listener).handleValueChange(this); } protected Object getListenerType() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangingEvent.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangingEvent.java index f92cde7b..f7a36770 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangingEvent.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueChangingEvent.java @@ -19,10 +19,13 @@ import org.eclipse.core.databinding.observable.ObservableEvent; * {@link IObservableValue} object's current value. Listeners can veto the * pending change by setting {@link #veto} to <code>true</code>. * + * @param <T> + * * @since 1.0 * */ -public class ValueChangingEvent extends ObservableEvent { +public class ValueChangingEvent<T> extends + ObservableEvent<ValueChangingEvent<T>> { /** * @@ -35,11 +38,11 @@ public class ValueChangingEvent extends ObservableEvent { * Description of the change to the source observable value. Listeners must * not change this field. */ - public ValueDiff diff; + public ValueDiff<T> diff; /** - * Flag for vetoing this change. Default value is <code>false</code>, can - * be set to <code>true</code> by listeners to veto this change. + * Flag for vetoing this change. Default value is <code>false</code>, can be + * set to <code>true</code> by listeners to veto this change. */ public boolean veto = false; @@ -51,7 +54,7 @@ public class ValueChangingEvent extends ObservableEvent { * @param diff * the value change */ - public ValueChangingEvent(IObservableValue source, ValueDiff diff) { + public ValueChangingEvent(IObservableValue<T> source, ValueDiff<T> diff) { super(source); this.diff = diff; } @@ -59,12 +62,12 @@ public class ValueChangingEvent extends ObservableEvent { /** * @return the observable value from which this event originated */ - public IObservableValue getObservableValue() { - return (IObservableValue) source; + public IObservableValue<?> getObservableValue() { + return (IObservableValue<?>) source; } protected void dispatch(IObservablesListener listener) { - ((IValueChangingListener) listener).handleValueChanging(this); + ((IValueChangingListener<T>) listener).handleValueChanging(this); } protected Object getListenerType() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueDiff.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueDiff.java index 8e26ef64..4bc88e5d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueDiff.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/ValueDiff.java @@ -16,10 +16,11 @@ import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.IDiff; /** + * @param <T> * @since 1.0 * */ -public abstract class ValueDiff implements IDiff { +public abstract class ValueDiff<T> implements IDiff { /** * Creates a value diff. */ @@ -29,16 +30,16 @@ public abstract class ValueDiff implements IDiff { /** * @return the old value */ - public abstract Object getOldValue(); + public abstract T getOldValue(); /** * @return the new value */ - public abstract Object getNewValue(); + public abstract T getNewValue(); public boolean equals(Object obj) { if (obj instanceof ValueDiff) { - ValueDiff val = (ValueDiff) obj; + ValueDiff<?> val = (ValueDiff<?>) obj; return Diffs.equals(val.getNewValue(), getNewValue()) && Diffs.equals(val.getOldValue(), getOldValue()); @@ -46,7 +47,7 @@ public abstract class ValueDiff implements IDiff { } return false; } - + public int hashCode() { final int prime = 31; int result = 1; @@ -62,14 +63,15 @@ public abstract class ValueDiff implements IDiff { */ public String toString() { StringBuffer buffer = new StringBuffer(); - buffer - .append(getClass().getName()) - .append("{oldValue [") //$NON-NLS-1$ - .append(getOldValue() != null ? getOldValue().toString() : "null") //$NON-NLS-1$ - .append("], newValue [") //$NON-NLS-1$ - .append(getNewValue() != null ? getNewValue().toString() : "null") //$NON-NLS-1$ - .append("]}"); //$NON-NLS-1$ - + buffer.append(getClass().getName()) + .append("{oldValue [") //$NON-NLS-1$ + .append(getOldValue() != null ? getOldValue().toString() + : "null") //$NON-NLS-1$ + .append("], newValue [") //$NON-NLS-1$ + .append(getNewValue() != null ? getNewValue().toString() + : "null") //$NON-NLS-1$ + .append("]}"); //$NON-NLS-1$ + return buffer.toString(); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/WritableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/WritableValue.java index 45e469ef..ac7b8e87 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/WritableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/value/WritableValue.java @@ -19,16 +19,18 @@ import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.Realm; /** - * Mutable (writable) implementation of {@link IObservableValue} that will maintain a value and fire - * change events when the value changes. + * Mutable (writable) implementation of {@link IObservableValue} that will + * maintain a value and fire change events when the value changes. * <p> * This class is thread safe. All state accessing methods must be invoked from * the {@link Realm#isCurrent() current realm}. Methods for adding and removing * listeners may be invoked from any thread. * </p> + * + * @param <T> * @since 1.0 */ -public class WritableValue extends AbstractObservableValue { +public class WritableValue<T> extends AbstractObservableValue<T> { private final Object valueType; @@ -48,7 +50,7 @@ public class WritableValue extends AbstractObservableValue { * @param valueType * can be <code>null</code> */ - public WritableValue(Object initialValue, Object valueType) { + public WritableValue(T initialValue, Object valueType) { this(Realm.getDefault(), initialValue, valueType); } @@ -71,15 +73,15 @@ public class WritableValue extends AbstractObservableValue { * @param valueType * can be <code>null</code> */ - public WritableValue(Realm realm, Object initialValue, Object valueType) { + public WritableValue(Realm realm, T initialValue, Object valueType) { super(realm); this.valueType = valueType; this.value = initialValue; } - private Object value = null; + private T value = null; - public Object doGetValue() { + public T doGetValue() { return value; } @@ -87,10 +89,11 @@ public class WritableValue extends AbstractObservableValue { * @param value * The value to set. */ - public void doSetValue(Object value) { - if (this.value != value) { - fireValueChange(Diffs.createValueDiff(this.value, this.value = value)); - } + public void doSetValue(T value) { + if (this.value != value) { + fireValueChange(Diffs.createValueDiff(this.value, + this.value = value)); + } } public Object getValueType() { @@ -98,10 +101,13 @@ public class WritableValue extends AbstractObservableValue { } /** - * @param elementType can be <code>null</code> - * @return new instance with the default realm and a value of <code>null</code> + * @param <T2> + * @param elementType + * can be <code>null</code> + * @return new instance with the default realm and a value of + * <code>null</code> */ - public static WritableValue withValueType(Object elementType) { - return new WritableValue(Realm.getDefault(), null, elementType); + public static <T2> WritableValue<T2> withValueType(Object elementType) { + return new WritableValue<T2>(Realm.getDefault(), null, elementType); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityMap.java index 334dc2fe..bd98bab3 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityMap.java @@ -33,16 +33,18 @@ import org.eclipse.core.runtime.Assert; * It intentionally violates the {@link Map} contract, which requires the use of * {@link #equals(Object)} when comparing keys. * + * @param <K> + * @param <V> * @since 1.2 */ -public class IdentityMap implements Map { - private Map wrappedMap; +public class IdentityMap<K, V> implements Map<K, V> { + private Map<IdentityWrapper<K>, V> wrappedMap; /** * Constructs an IdentityMap. */ public IdentityMap() { - this.wrappedMap = new HashMap(); + this.wrappedMap = new HashMap<IdentityWrapper<K>, V>(); } /** @@ -52,7 +54,7 @@ public class IdentityMap implements Map { * @param map * the map whose entries are to be added to this map. */ - public IdentityMap(Map map) { + public IdentityMap(Map<? extends K, ? extends V> map) { this(); Assert.isNotNull(map); putAll(map); @@ -70,14 +72,15 @@ public class IdentityMap implements Map { return wrappedMap.containsValue(value); } - public Set entrySet() { - final Set wrappedEntrySet = wrappedMap.entrySet(); - return new Set() { - public boolean add(Object o) { + public Set<Map.Entry<K, V>> entrySet() { + final Set<Map.Entry<IdentityWrapper<K>, V>> wrappedEntrySet = wrappedMap + .entrySet(); + return new Set<Map.Entry<K, V>>() { + public boolean add(Map.Entry<K, V> o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends Map.Entry<K, V>> c) { throw new UnsupportedOperationException(); } @@ -86,14 +89,15 @@ public class IdentityMap implements Map { } public boolean contains(Object o) { - for (Iterator iterator = iterator(); iterator.hasNext();) + for (Iterator<Map.Entry<K, V>> 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();) + public boolean containsAll(Collection<?> c) { + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) if (!contains(iterator.next())) return false; return true; @@ -103,27 +107,27 @@ public class IdentityMap implements Map { return wrappedEntrySet.isEmpty(); } - public Iterator iterator() { - final Iterator wrappedIterator = wrappedEntrySet.iterator(); - return new Iterator() { + public Iterator<Map.Entry<K, V>> iterator() { + final Iterator<Map.Entry<IdentityWrapper<K>, V>> wrappedIterator = wrappedEntrySet + .iterator(); + return new Iterator<Map.Entry<K, V>>() { public boolean hasNext() { return wrappedIterator.hasNext(); } - public Object next() { - final Map.Entry wrappedEntry = (Map.Entry) wrappedIterator + public Map.Entry<K, V> next() { + final Map.Entry<IdentityWrapper<K>, V> wrappedEntry = wrappedIterator .next(); - return new Map.Entry() { - public Object getKey() { - return ((IdentityWrapper) wrappedEntry.getKey()) - .unwrap(); + return new Map.Entry<K, V>() { + public K getKey() { + return wrappedEntry.getKey().unwrap(); } - public Object getValue() { + public V getValue() { return wrappedEntry.getValue(); } - public Object setValue(Object value) { + public V setValue(V value) { return wrappedEntry.setValue(value); } @@ -132,10 +136,10 @@ public class IdentityMap implements Map { return true; if (obj == null || !(obj instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) obj; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) obj; return this.getKey() == that.getKey() - && Util.equals(this.getValue(), that - .getValue()); + && Util.equals(this.getValue(), + that.getValue()); } public int hashCode() { @@ -151,11 +155,12 @@ public class IdentityMap implements Map { } public boolean remove(Object o) { - final Map.Entry unwrappedEntry = (Map.Entry) o; - final IdentityWrapper wrappedKey = IdentityWrapper - .wrap(unwrappedEntry.getKey()); - Map.Entry wrappedEntry = new Map.Entry() { - public Object getKey() { + final Map.Entry<?, ?> unwrappedEntry = (Map.Entry<?, ?>) o; + Object key = unwrappedEntry.getKey(); + final IdentityWrapper<Object> wrappedKey = IdentityWrapper + .wrap(key); + Map.Entry<IdentityWrapper<Object>, Object> wrappedEntry = new Map.Entry<IdentityWrapper<Object>, Object>() { + public IdentityWrapper<Object> getKey() { return wrappedKey; } @@ -172,11 +177,9 @@ public class IdentityMap implements Map { return true; if (obj == null || !(obj instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) obj; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) obj; return Util.equals(wrappedKey, that.getKey()) - && Util - .equals(this.getValue(), that - .getValue()); + && Util.equals(this.getValue(), that.getValue()); } public int hashCode() { @@ -188,17 +191,18 @@ public class IdentityMap implements Map { return wrappedEntrySet.remove(wrappedEntry); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { boolean changed = false; - for (Iterator iterator = c.iterator(); iterator.hasNext();) + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) changed |= remove(iterator.next()); return changed; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { boolean changed = false; Object[] toRetain = c.toArray(); - outer: for (Iterator iterator = iterator(); iterator.hasNext();) { + outer: for (Iterator<?> iterator = iterator(); iterator + .hasNext();) { Object entry = iterator.next(); for (int i = 0; i < toRetain.length; i++) if (entry.equals(toRetain[i])) @@ -217,16 +221,16 @@ public class IdentityMap implements Map { return toArray(new Object[size()]); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) { - a = (Object[]) Array.newInstance(a.getClass() - .getComponentType(), size); + a = (T[]) Array.newInstance( + a.getClass().getComponentType(), size); } int i = 0; - for (Iterator iterator = iterator(); iterator.hasNext();) { - a[i] = iterator.next(); - i++; + for (Iterator<Map.Entry<K, V>> iterator = iterator(); iterator + .hasNext();) { + a[i++] = (T) iterator.next(); } return a; } @@ -236,7 +240,7 @@ public class IdentityMap implements Map { return true; if (obj == null || !(obj instanceof Set)) return false; - Set that = (Set) obj; + Set<?> that = (Set<?>) obj; return this.size() == that.size() && containsAll(that); } @@ -246,7 +250,7 @@ public class IdentityMap implements Map { }; } - public Object get(Object key) { + public V get(Object key) { return wrappedMap.get(IdentityWrapper.wrap(key)); } @@ -254,14 +258,14 @@ public class IdentityMap implements Map { return wrappedMap.isEmpty(); } - public Set keySet() { - final Set wrappedKeySet = wrappedMap.keySet(); - return new Set() { - public boolean add(Object o) { + public Set<K> keySet() { + final Set<IdentityWrapper<K>> wrappedKeySet = wrappedMap.keySet(); + return new Set<K>() { + public boolean add(K o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends K> c) { throw new UnsupportedOperationException(); } @@ -273,8 +277,8 @@ public class IdentityMap implements Map { return wrappedKeySet.contains(IdentityWrapper.wrap(o)); } - public boolean containsAll(Collection c) { - for (Iterator iterator = c.iterator(); iterator.hasNext();) + public boolean containsAll(Collection<?> c) { + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) if (!wrappedKeySet.contains(IdentityWrapper.wrap(iterator .next()))) return false; @@ -285,16 +289,16 @@ public class IdentityMap implements Map { return wrappedKeySet.isEmpty(); } - public Iterator iterator() { - final Iterator wrappedIterator = wrappedKeySet.iterator(); - return new Iterator() { + public Iterator<K> iterator() { + final Iterator<IdentityWrapper<K>> wrappedIterator = wrappedKeySet + .iterator(); + return new Iterator<K>() { public boolean hasNext() { return wrappedIterator.hasNext(); } - public Object next() { - return ((IdentityWrapper) wrappedIterator.next()) - .unwrap(); + public K next() { + return wrappedIterator.next().unwrap(); } public void remove() { @@ -307,18 +311,19 @@ public class IdentityMap implements Map { return wrappedKeySet.remove(IdentityWrapper.wrap(o)); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { boolean changed = false; - for (Iterator iterator = c.iterator(); iterator.hasNext();) + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) changed |= wrappedKeySet.remove(IdentityWrapper .wrap(iterator.next())); return changed; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { boolean changed = false; Object[] toRetain = c.toArray(); - outer: for (Iterator iterator = iterator(); iterator.hasNext();) { + outer: for (Iterator<?> iterator = iterator(); iterator + .hasNext();) { Object element = iterator.next(); for (int i = 0; i < toRetain.length; i++) if (element == toRetain[i]) @@ -338,17 +343,17 @@ public class IdentityMap implements Map { return toArray(new Object[wrappedKeySet.size()]); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { int size = wrappedKeySet.size(); - IdentityWrapper[] wrappedArray = (IdentityWrapper[]) wrappedKeySet - .toArray(new IdentityWrapper[size]); - Object[] result = a; + T[] result = a; if (a.length < size) { - result = (Object[]) Array.newInstance(a.getClass() + result = (T[]) Array.newInstance(a.getClass() .getComponentType(), size); } - for (int i = 0; i < size; i++) - result[i] = wrappedArray[i].unwrap(); + int i = 0; + for (IdentityWrapper<K> wrapper : wrappedKeySet) { + result[i++] = (T) wrapper.unwrap(); + } return result; } @@ -357,7 +362,7 @@ public class IdentityMap implements Map { return true; if (obj == null || !(obj instanceof Set)) return false; - Set that = (Set) obj; + Set<?> that = (Set<?>) obj; return this.size() == that.size() && containsAll(that); } @@ -367,20 +372,34 @@ public class IdentityMap implements Map { }; } - public Object put(Object key, Object value) { + public V put(K key, V value) { return wrappedMap.put(IdentityWrapper.wrap(key), value); } - public void putAll(Map other) { - for (Iterator iterator = other.entrySet().iterator(); iterator + public void putAll(Map<? extends K, ? extends V> other) { + // The following would be more efficient but JDT gives spurious errors + // on it. + + // Set<Map.Entry<? extends K, ? extends V>> entrySet = other.entrySet(); + // for (Iterator<Map.Entry<? extends K, ? extends V>> iterator = + // entrySet + // .iterator(); iterator.hasNext();) { + // Map.Entry<? extends K, ? extends V> entry = iterator.next(); + // K key = entry.getKey(); + // V value = entry.getValue(); + // wrappedMap.put(IdentityWrapper.wrap(key), value); + // } + + Set<? extends K> keySet = other.keySet(); + for (Iterator<? extends K> iterator = keySet.iterator(); iterator .hasNext();) { - Map.Entry entry = (Map.Entry) iterator.next(); - wrappedMap.put(IdentityWrapper.wrap(entry.getKey()), entry - .getValue()); + K key = iterator.next(); + V value = other.get(key); + wrappedMap.put(IdentityWrapper.wrap(key), value); } } - public Object remove(Object key) { + public V remove(Object key) { return wrappedMap.remove(IdentityWrapper.wrap(key)); } @@ -388,7 +407,7 @@ public class IdentityMap implements Map { return wrappedMap.size(); } - public Collection values() { + public Collection<V> values() { return wrappedMap.values(); } @@ -397,7 +416,7 @@ public class IdentityMap implements Map { return true; if (obj == null || !(obj instanceof Map)) return false; - Map that = (Map) obj; + Map<?, ?> that = (Map<?, ?>) obj; return this.entrySet().equals(that.entrySet()); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityObservableSet.java index 15a34318..b09ef4ee 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityObservableSet.java @@ -33,10 +33,12 @@ import org.eclipse.core.databinding.observable.set.IObservableSet; * interface. It intentionally violates the {@link Set} contract, which requires * the use of {@link #equals(Object)} when comparing elements. * + * @param <E> + * * @since 1.2 */ -public class IdentityObservableSet extends AbstractObservableSet { - private Set wrappedSet; +public class IdentityObservableSet<E> extends AbstractObservableSet<E> { + private Set<E> wrappedSet; private Object elementType; /** @@ -50,11 +52,11 @@ public class IdentityObservableSet extends AbstractObservableSet { public IdentityObservableSet(Realm realm, Object elementType) { super(realm); - this.wrappedSet = new IdentitySet(); + this.wrappedSet = new IdentitySet<E>(); this.elementType = elementType; } - protected Set getWrappedSet() { + protected Set<E> getWrappedSet() { return wrappedSet; } @@ -62,18 +64,18 @@ public class IdentityObservableSet extends AbstractObservableSet { return elementType; } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - final Iterator wrappedIterator = wrappedSet.iterator(); - return new Iterator() { - Object last; + final Iterator<E> wrappedIterator = wrappedSet.iterator(); + return new Iterator<E>() { + E last; public boolean hasNext() { getterCalled(); return wrappedIterator.hasNext(); } - public Object next() { + public E next() { getterCalled(); return last = wrappedIterator.next(); } @@ -81,65 +83,75 @@ public class IdentityObservableSet extends AbstractObservableSet { public void remove() { getterCalled(); wrappedIterator.remove(); - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, + Set<E> emptySet = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(emptySet, Collections.singleton(last))); } }; } - public boolean add(Object o) { + public boolean add(E o) { getterCalled(); boolean changed = wrappedSet.add(o); - if (changed) + if (changed) { + Set<E> emptySet = Collections.emptySet(); fireSetChange(Diffs.createSetDiff(Collections.singleton(o), - Collections.EMPTY_SET)); + emptySet)); + } return changed; } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { getterCalled(); - Set additions = new IdentitySet(); - for (Iterator iterator = c.iterator(); iterator.hasNext();) { - Object element = iterator.next(); + Set<E> additions = new IdentitySet<E>(); + for (Iterator<? extends E> iterator = c.iterator(); iterator.hasNext();) { + E element = iterator.next(); if (wrappedSet.add(element)) additions.add(element); } boolean changed = !additions.isEmpty(); - if (changed) - fireSetChange(Diffs.createSetDiff(additions, Collections.EMPTY_SET)); + if (changed) { + Set<E> emptySet = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, emptySet)); + } return changed; } public boolean remove(Object o) { getterCalled(); boolean changed = wrappedSet.remove(o); - if (changed) - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, - Collections.singleton(o))); + if (changed) { + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, + Collections.singleton((E) o))); + } return changed; } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { getterCalled(); - Set removals = new IdentitySet(); - for (Iterator iterator = c.iterator(); iterator.hasNext();) { + Set<E> removals = new IdentitySet<E>(); + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) { Object element = iterator.next(); - if (wrappedSet.remove(element)) - removals.add(element); + if (wrappedSet.remove(element)) { + removals.add((E) element); + } } boolean changed = !removals.isEmpty(); - if (changed) - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals)); + if (changed) { + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, removals)); + } return changed; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { getterCalled(); - Set removals = new IdentitySet(); + Set<E> removals = new IdentitySet<E>(); Object[] toRetain = c.toArray(); - outer: for (Iterator iterator = wrappedSet.iterator(); iterator + outer: for (Iterator<E> iterator = wrappedSet.iterator(); iterator .hasNext();) { - Object element = iterator.next(); + E element = iterator.next(); // Cannot rely on c.contains(element) because we must compare // elements using IElementComparer. for (int i = 0; i < toRetain.length; i++) { @@ -150,17 +162,20 @@ public class IdentityObservableSet extends AbstractObservableSet { removals.add(element); } boolean changed = !removals.isEmpty(); - if (changed) - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals)); + if (changed) { + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, removals)); + } return changed; } public void clear() { getterCalled(); if (!wrappedSet.isEmpty()) { - Set removals = wrappedSet; - wrappedSet = new IdentitySet(); - fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals)); + Set<E> removals = wrappedSet; + wrappedSet = new IdentitySet<E>(); + Set<E> additions = Collections.emptySet(); + fireSetChange(Diffs.createSetDiff(additions, removals)); } } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentitySet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentitySet.java index 4bf6388c..c5fadc3d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentitySet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentitySet.java @@ -29,16 +29,17 @@ import java.util.Set; * It intentionally violates the {@link Set} contract, which requires the use of * {@link #equals(Object)} when comparing elements. * + * @param <E> * @since 1.2 */ -public class IdentitySet implements Set { - private final Set wrappedSet; +public class IdentitySet<E> implements Set<E> { + private final Set<IdentityWrapper<E>> wrappedSet; /** * Constructs an IdentitySet. */ public IdentitySet() { - this.wrappedSet = new HashSet(); + this.wrappedSet = new HashSet<IdentityWrapper<E>>(); } /** @@ -48,19 +49,21 @@ public class IdentitySet implements Set { * @param collection * the collection whose elements are to be added to this set. */ - public IdentitySet(Collection collection) { + public IdentitySet(Collection<? extends E> collection) { this(); addAll(collection); } - public boolean add(Object o) { + public boolean add(E o) { return wrappedSet.add(IdentityWrapper.wrap(o)); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { boolean changed = false; - for (Iterator iterator = c.iterator(); iterator.hasNext();) - changed |= wrappedSet.add(IdentityWrapper.wrap(iterator.next())); + for (Iterator<? extends E> iterator = c.iterator(); iterator.hasNext();) { + E element = iterator.next(); + changed |= wrappedSet.add(IdentityWrapper.wrap(element)); + } return changed; } @@ -72,8 +75,8 @@ public class IdentitySet implements Set { return wrappedSet.contains(IdentityWrapper.wrap(o)); } - public boolean containsAll(Collection c) { - for (Iterator iterator = c.iterator(); iterator.hasNext();) + public boolean containsAll(Collection<?> c) { + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) if (!wrappedSet.contains(IdentityWrapper.wrap(iterator.next()))) return false; return true; @@ -83,15 +86,16 @@ public class IdentitySet implements Set { return wrappedSet.isEmpty(); } - public Iterator iterator() { - final Iterator wrappedIterator = wrappedSet.iterator(); - return new Iterator() { + public Iterator<E> iterator() { + final Iterator<IdentityWrapper<E>> wrappedIterator = wrappedSet + .iterator(); + return new Iterator<E>() { public boolean hasNext() { return wrappedIterator.hasNext(); } - public Object next() { - return ((IdentityWrapper) wrappedIterator.next()).unwrap(); + public E next() { + return wrappedIterator.next().unwrap(); } public void remove() { @@ -104,21 +108,21 @@ public class IdentitySet implements Set { return wrappedSet.remove(IdentityWrapper.wrap(o)); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { boolean changed = false; - for (Iterator iterator = c.iterator(); iterator.hasNext();) + for (Iterator<?> iterator = c.iterator(); iterator.hasNext();) changed |= remove(iterator.next()); return changed; } - public boolean retainAll(Collection c) { + 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(); + outer: for (Iterator<E> iterator = iterator(); iterator.hasNext();) { + E element = iterator.next(); for (int i = 0; i < retainAll.length; i++) { if (element == retainAll[i]) { continue outer; @@ -138,17 +142,18 @@ public class IdentitySet implements Set { return toArray(new Object[wrappedSet.size()]); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { int size = wrappedSet.size(); - IdentityWrapper[] wrappedArray = (IdentityWrapper[]) wrappedSet - .toArray(new IdentityWrapper[size]); - Object[] result = a; + T[] result = a; if (a.length < size) { - result = (Object[]) Array.newInstance(a.getClass() - .getComponentType(), size); + result = (T[]) Array.newInstance(a.getClass().getComponentType(), + size); + } + + int i = 0; + for (IdentityWrapper<? extends E> wrapper : wrappedSet) { + result[i++] = (T) wrapper.unwrap(); } - for (int i = 0; i < size; i++) - result[i] = wrappedArray[i].unwrap(); return result; } @@ -157,14 +162,14 @@ public class IdentitySet implements Set { return true; if (!(obj instanceof Set)) return false; - Set that = (Set) obj; + 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(); + for (Iterator<E> iterator = iterator(); iterator.hasNext();) { + E element = iterator.next(); hash += element == null ? 0 : element.hashCode(); } return hash; diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityWrapper.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityWrapper.java index 9e140c5a..15ccde5a 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityWrapper.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/identity/IdentityWrapper.java @@ -18,35 +18,36 @@ package org.eclipse.core.internal.databinding.identity; * and hashCode() when putting them in sets or hashmaps to ensure identity * comparison. * + * @param <T> * @since 1.0 * */ -public class IdentityWrapper { - private static final IdentityWrapper NULL_WRAPPER = new IdentityWrapper( - null); +public class IdentityWrapper<T> { /** + * @param <T> * @param o * the object to wrap * @return an IdentityWrapper wrapping the specified object */ - public static IdentityWrapper wrap(Object o) { - return o == null ? NULL_WRAPPER : new IdentityWrapper(o); + public static <T> IdentityWrapper<T> wrap(T o) { + return o == null ? new IdentityWrapper<T>(null) + : new IdentityWrapper<T>(o); } - final Object o; + final T o; /** * @param o */ - private IdentityWrapper(Object o) { + private IdentityWrapper(T o) { this.o = o; } /** * @return the unwrapped object */ - public Object unwrap() { + public T unwrap() { return o; } @@ -54,7 +55,7 @@ public class IdentityWrapper { if (obj == null || obj.getClass() != IdentityWrapper.class) { return false; } - return o == ((IdentityWrapper) obj).o; + return o == ((IdentityWrapper<?>) obj).o; } public int hashCode() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/Activator.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/Activator.java index b8b78b02..a618503a 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/Activator.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/Activator.java @@ -33,7 +33,7 @@ public class Activator implements BundleActivator { */ public static final String PLUGIN_ID = "org.eclipse.core.databinding"; //$NON-NLS-1$ - private volatile static ServiceTracker _frameworkLogTracker; + private volatile static ServiceTracker<FrameworkLog, FrameworkLog> _frameworkLogTracker; /** * The constructor @@ -42,20 +42,23 @@ public class Activator implements BundleActivator { } public void start(BundleContext context) throws Exception { - _frameworkLogTracker = new ServiceTracker(context, FrameworkLog.class.getName(), null); + _frameworkLogTracker = new ServiceTracker<FrameworkLog, FrameworkLog>( + context, FrameworkLog.class, null); _frameworkLogTracker.open(); Policy.setLog(new ILogger() { public void log(IStatus status) { - ServiceTracker frameworkLogTracker = _frameworkLogTracker; - FrameworkLog log = frameworkLogTracker == null ? null : (FrameworkLog) frameworkLogTracker.getService(); + ServiceTracker<FrameworkLog, FrameworkLog> frameworkLogTracker = _frameworkLogTracker; + FrameworkLog log = frameworkLogTracker == null ? null + : frameworkLogTracker.getService(); if (log != null) { log.log(createLogEntry(status)); } else { // fall back to System.err - System.err.println(status.getPlugin() + " - " + status.getCode() + " - " + status.getMessage()); //$NON-NLS-1$//$NON-NLS-2$ - if( status.getException() != null ) { + System.err.println(status.getPlugin() + + " - " + status.getCode() + " - " + status.getMessage()); //$NON-NLS-1$//$NON-NLS-2$ + if (status.getException() != null) { status.getException().printStackTrace(System.err); } } @@ -63,15 +66,15 @@ public class Activator implements BundleActivator { }); } - + // Code copied from PlatformLogWriter.getLog(). Why is logging an IStatus so // hard? FrameworkLogEntry createLogEntry(IStatus status) { Throwable t = status.getException(); - ArrayList childlist = new ArrayList(); + ArrayList<FrameworkLogEntry> childlist = new ArrayList<FrameworkLogEntry>(); int stackCode = t instanceof CoreException ? 1 : 0; - // ensure a substatus inside a CoreException is properly logged + // ensure a substatus inside a CoreException is properly logged if (stackCode == 1) { IStatus coreStatus = ((CoreException) t).getStatus(); if (coreStatus != null) { @@ -86,12 +89,13 @@ public class Activator implements BundleActivator { } } - FrameworkLogEntry[] children = (FrameworkLogEntry[]) (childlist.size() == 0 ? null : childlist.toArray(new FrameworkLogEntry[childlist.size()])); + FrameworkLogEntry[] children = (childlist.size() == 0 ? null + : childlist.toArray(new FrameworkLogEntry[childlist.size()])); - return new FrameworkLogEntry(status.getPlugin(), status.getSeverity(), status.getCode(), status.getMessage(), stackCode, t, children); + return new FrameworkLogEntry(status.getPlugin(), status.getSeverity(), + status.getCode(), status.getMessage(), stackCode, t, children); } - public void stop(BundleContext context) throws Exception { if (_frameworkLogTracker != null) { _frameworkLogTracker.close(); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/ConstantObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/ConstantObservableValue.java index f971420d..d98a5246 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/ConstantObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/ConstantObservableValue.java @@ -24,11 +24,13 @@ import org.eclipse.core.runtime.Assert; /** * An immutable {@link IObservableValue}. * + * @param <T> + * * @see WritableValue */ -public class ConstantObservableValue implements IObservableValue { +public class ConstantObservableValue<T> implements IObservableValue<T> { final Realm realm; - final Object value; + final T value; final Object type; /** @@ -39,7 +41,7 @@ public class ConstantObservableValue implements IObservableValue { * @param type * type */ - public ConstantObservableValue(Object value, Object type) { + public ConstantObservableValue(T value, Object type) { this(Realm.getDefault(), value, type); } @@ -53,7 +55,7 @@ public class ConstantObservableValue implements IObservableValue { * @param type * type */ - public ConstantObservableValue(Realm realm, Object value, Object type) { + public ConstantObservableValue(Realm realm, T value, Object type) { Assert.isNotNull(realm, "Realm cannot be null"); //$NON-NLS-1$ this.realm = realm; this.value = value; @@ -65,20 +67,20 @@ public class ConstantObservableValue implements IObservableValue { return type; } - public Object getValue() { + public T getValue() { ObservableTracker.getterCalled(this); return value; } - public void setValue(Object value) { + public void setValue(T value) { throw new UnsupportedOperationException(); } - public void addValueChangeListener(IValueChangeListener listener) { + public void addValueChangeListener(IValueChangeListener<T> listener) { // ignore } - public void removeValueChangeListener(IValueChangeListener listener) { + public void removeValueChangeListener(IValueChangeListener<T> listener) { // ignore } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/DelayedObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/DelayedObservableValue.java index 1741c35d..2862dfb6 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/DelayedObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/DelayedObservableValue.java @@ -40,17 +40,19 @@ import org.eclipse.core.databinding.observable.value.ValueDiff; * Note that this class will not forward {@link ValueChangingEvent} events from * a wrapped {@link IVetoableValue}. * + * @param <T> + * * @since 1.2 */ -public class DelayedObservableValue extends AbstractObservableValue implements - IStaleListener, IValueChangeListener { +public class DelayedObservableValue<T> extends AbstractObservableValue<T> + implements IStaleListener, IValueChangeListener<T> { class ValueUpdater implements Runnable { - private final Object oldValue; + private final T oldValue; boolean cancel = false; boolean running = false; - ValueUpdater(Object oldValue) { + ValueUpdater(T oldValue) { this.oldValue = oldValue; } @@ -70,10 +72,10 @@ public class DelayedObservableValue extends AbstractObservableValue implements } private final int delay; - private IObservableValue observable; + private IObservableValue<T> observable; private boolean dirty = true; - private Object cachedValue = null; + private T cachedValue = null; private boolean updating = false; @@ -90,7 +92,8 @@ public class DelayedObservableValue extends AbstractObservableValue implements * @throws IllegalArgumentException * if <code>updateEventType</code> is an incorrect type. */ - public DelayedObservableValue(int delayMillis, IObservableValue observable) { + public DelayedObservableValue(int delayMillis, + IObservableValue<T> observable) { super(observable.getRealm()); this.delay = delayMillis; this.observable = observable; @@ -101,7 +104,7 @@ public class DelayedObservableValue extends AbstractObservableValue implements cachedValue = doGetValue(); } - public void handleValueChange(ValueChangeEvent event) { + public void handleValueChange(ValueChangeEvent<T> event) { if (!updating) makeDirty(); } @@ -111,7 +114,7 @@ public class DelayedObservableValue extends AbstractObservableValue implements fireStale(); } - protected Object doGetValue() { + protected T doGetValue() { if (dirty) { cachedValue = observable.getValue(); dirty = false; @@ -125,7 +128,7 @@ public class DelayedObservableValue extends AbstractObservableValue implements return cachedValue; } - protected void doSetValue(Object value) { + protected void doSetValue(T value) { updating = true; try { // Principle of least surprise: setValue overrides any pending @@ -133,7 +136,7 @@ public class DelayedObservableValue extends AbstractObservableValue implements dirty = false; cancelScheduledUpdate(); - Object oldValue = cachedValue; + T oldValue = cachedValue; observable.setValue(value); // Bug 215297 - target observable could veto or override value // passed to setValue(). Make sure we cache whatever is set. @@ -191,14 +194,14 @@ public class DelayedObservableValue extends AbstractObservableValue implements getRealm().timerExec(delay, updater); } - private void internalFireValueChange(final Object oldValue) { + private void internalFireValueChange(final T oldValue) { cancelScheduledUpdate(); - fireValueChange(new ValueDiff() { - public Object getOldValue() { + fireValueChange(new ValueDiff<T>() { + public T getOldValue() { return oldValue; } - public Object getNewValue() { + public T getNewValue() { return getValue(); } }); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableList.java index f97a7f29..531d2b5a 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableList.java @@ -29,17 +29,19 @@ import org.eclipse.core.runtime.Assert; /** * Singleton empty list + * + * @param <E> */ -public class EmptyObservableList implements IObservableList { +public class EmptyObservableList<E> implements IObservableList<E> { - private static final List emptyList = Collections.EMPTY_LIST; + private final List<E> emptyList = Collections.emptyList(); private final Realm realm; private Object elementType; /** - * Creates an empty list. This list may be disposed multiple times - * without any side-effects. + * Creates an empty list. This list may be disposed multiple times without + * any side-effects. * * @param realm * the realm of the constructed list @@ -49,8 +51,8 @@ public class EmptyObservableList implements IObservableList { } /** - * Creates an empty list. This list may be disposed multiple times - * without any side-effects. + * Creates an empty list. This list may be disposed multiple times without + * any side-effects. * * @param realm * the realm of the constructed list @@ -64,11 +66,11 @@ public class EmptyObservableList implements IObservableList { ObservableTracker.observableCreated(this); } - public void addListChangeListener(IListChangeListener listener) { + public void addListChangeListener(IListChangeListener<E> listener) { // ignore } - public void removeListChangeListener(IListChangeListener listener) { + public void removeListChangeListener(IListChangeListener<E> listener) { // ignore } @@ -96,7 +98,7 @@ public class EmptyObservableList implements IObservableList { return false; } - public Iterator iterator() { + public Iterator<E> iterator() { checkRealm(); return emptyList.iterator(); } @@ -106,11 +108,11 @@ public class EmptyObservableList implements IObservableList { return emptyList.toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { return emptyList.toArray(a); } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } @@ -118,20 +120,20 @@ public class EmptyObservableList implements IObservableList { throw new UnsupportedOperationException(); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { checkRealm(); return c.isEmpty(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -169,11 +171,11 @@ public class EmptyObservableList implements IObservableList { public void dispose() { } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public Object get(int index) { + public E get(int index) { return emptyList.get(index); } @@ -185,31 +187,31 @@ public class EmptyObservableList implements IObservableList { return -1; } - public ListIterator listIterator() { + public ListIterator<E> listIterator() { return emptyList.listIterator(); } - public ListIterator listIterator(int index) { + public ListIterator<E> listIterator(int index) { return emptyList.listIterator(index); } - public Object remove(int index) { + public E remove(int index) { throw new UnsupportedOperationException(); } - public Object set(int index, Object element) { + public E set(int index, E element) { throw new UnsupportedOperationException(); } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { throw new UnsupportedOperationException(); } - public List subList(int fromIndex, int toIndex) { + public List<E> subList(int fromIndex, int toIndex) { return emptyList.subList(fromIndex, toIndex); } - public void add(int index, Object o) { + public void add(int index, E o) { throw new UnsupportedOperationException(); } @@ -226,7 +228,7 @@ public class EmptyObservableList implements IObservableList { if (!(obj instanceof List)) return false; - return ((List) obj).isEmpty(); + return ((List<?>) obj).isEmpty(); } public int hashCode() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableSet.java index 1bd73258..bc3aea95 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/EmptyObservableSet.java @@ -28,10 +28,12 @@ import org.eclipse.core.runtime.Assert; /** * Singleton empty set + * + * @param <E> */ -public class EmptyObservableSet implements IObservableSet { +public class EmptyObservableSet<E> implements IObservableSet<E> { - private static final Set emptySet = Collections.EMPTY_SET; + private final Set<E> emptySet = Collections.emptySet(); private final Realm realm; private Object elementType; @@ -63,10 +65,10 @@ public class EmptyObservableSet implements IObservableSet { ObservableTracker.observableCreated(this); } - public void addSetChangeListener(ISetChangeListener listener) { + public void addSetChangeListener(ISetChangeListener<? super E> listener) { } - public void removeSetChangeListener(ISetChangeListener listener) { + public void removeSetChangeListener(ISetChangeListener<? super E> listener) { } public Object getElementType() { @@ -93,7 +95,7 @@ public class EmptyObservableSet implements IObservableSet { return false; } - public Iterator iterator() { + public Iterator<E> iterator() { checkRealm(); return emptySet.iterator(); } @@ -103,11 +105,11 @@ public class EmptyObservableSet implements IObservableSet { return emptySet.toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { return emptySet.toArray(a); } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } @@ -115,20 +117,20 @@ public class EmptyObservableSet implements IObservableSet { throw new UnsupportedOperationException(); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { checkRealm(); return c.isEmpty(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -179,7 +181,7 @@ public class EmptyObservableSet implements IObservableSet { if (!(obj instanceof Set)) return false; - return ((Set) obj).isEmpty(); + return ((Set<?>) obj).isEmpty(); } public int hashCode() { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/MapEntryObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/MapEntryObservableValue.java index 3340eb6e..3a59b9e3 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/MapEntryObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/MapEntryObservableValue.java @@ -26,25 +26,29 @@ import org.eclipse.core.databinding.observable.value.IObservableValue; * An {@link IObservableValue} that tracks the value of an entry in an * {@link IObservableMap}, identified by the entry's key. * + * @param <K> + * @param <V> + * * @since 1.1 */ -public class MapEntryObservableValue extends AbstractObservableValue { - private IObservableMap map; - private Object key; +public class MapEntryObservableValue<K, V> extends AbstractObservableValue<V> { + private IObservableMap<K, V> map; + private K key; private Object valueType; - private IMapChangeListener changeListener = new IMapChangeListener() { - public void handleMapChange(final MapChangeEvent event) { + private IMapChangeListener<K, V> changeListener = new IMapChangeListener<K, V>() { + public void handleMapChange(final MapChangeEvent<K, V> event) { if (event.diff.getAddedKeys().contains(key)) { - final Object newValue = event.diff.getNewValue(key); + final V newValue = event.diff.getNewValue(key); if (newValue != null) { fireValueChange(Diffs.createValueDiff(null, newValue)); } } else if (event.diff.getChangedKeys().contains(key)) { - fireValueChange(Diffs.createValueDiff(event.diff - .getOldValue(key), event.diff.getNewValue(key))); + fireValueChange(Diffs.createValueDiff( + event.diff.getOldValue(key), + event.diff.getNewValue(key))); } else if (event.diff.getRemovedKeys().contains(key)) { - final Object oldValue = event.diff.getOldValue(key); + final V oldValue = event.diff.getOldValue(key); if (oldValue != null) { fireValueChange(Diffs.createValueDiff(oldValue, null)); } @@ -68,7 +72,7 @@ public class MapEntryObservableValue extends AbstractObservableValue { * @param valueType * the type of the value */ - public MapEntryObservableValue(IObservableMap map, Object key, + public MapEntryObservableValue(IObservableMap<K, V> map, K key, Object valueType) { super(map.getRealm()); this.map = map; @@ -99,11 +103,11 @@ public class MapEntryObservableValue extends AbstractObservableValue { super.dispose(); } - protected Object doGetValue() { + protected V doGetValue() { return this.map.get(this.key); } - protected void doSetValue(Object value) { + protected void doSetValue(V value) { this.map.put(this.key, value); } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessObservableValue.java index 6a07fad3..5333d49a 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessObservableValue.java @@ -24,9 +24,9 @@ import org.eclipse.core.databinding.observable.value.AbstractObservableValue; * * @since 1.1 */ -public class StalenessObservableValue extends AbstractObservableValue { +public class StalenessObservableValue extends AbstractObservableValue<Boolean> { - private class MyListener implements IChangeListener, IStaleListener { + private class MyChangeListener implements IChangeListener { public void handleChange(ChangeEvent event) { if (stale && !event.getObservable().isStale()) { stale = false; @@ -34,7 +34,9 @@ public class StalenessObservableValue extends AbstractObservableValue { Boolean.FALSE)); } } + } + private class MyStaleListener implements IStaleListener { public void handleStale(StaleEvent staleEvent) { if (!stale) { stale = true; @@ -46,7 +48,8 @@ public class StalenessObservableValue extends AbstractObservableValue { private IObservable tracked; private boolean stale; - private MyListener listener = new MyListener(); + private MyChangeListener changeListener = new MyChangeListener(); + private MyStaleListener staleListener = new MyStaleListener(); /** * Constructs a StalenessObservableValue that tracks the staleness of the @@ -59,11 +62,11 @@ public class StalenessObservableValue extends AbstractObservableValue { super(observable.getRealm()); this.tracked = observable; this.stale = observable.isStale(); - tracked.addChangeListener(listener); - tracked.addStaleListener(listener); + tracked.addChangeListener(changeListener); + tracked.addStaleListener(staleListener); } - protected Object doGetValue() { + protected Boolean doGetValue() { return tracked.isStale() ? Boolean.TRUE : Boolean.FALSE; } @@ -73,10 +76,11 @@ public class StalenessObservableValue extends AbstractObservableValue { public synchronized void dispose() { if (tracked != null) { - tracked.removeChangeListener(listener); - tracked.removeStaleListener(listener); + tracked.removeChangeListener(changeListener); + tracked.removeStaleListener(staleListener); tracked = null; - listener = null; + changeListener = null; + staleListener = null; } super.dispose(); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java index d5c64caa..9cbc01ee 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/StalenessTracker.java @@ -27,27 +27,30 @@ import org.eclipse.core.internal.databinding.identity.IdentityMap; */ public class StalenessTracker { - private Map staleMap = new IdentityMap(); + private Map<IObservable, Boolean> staleMap = new IdentityMap<IObservable, Boolean>(); private int staleCount = 0; private final IStalenessConsumer stalenessConsumer; - private class ChildListener implements IStaleListener, IChangeListener { - public void handleStale(StaleEvent event) { + private class ChildChangeListener implements IChangeListener { + public void handleChange(ChangeEvent event) { processStalenessChange((IObservable) event.getSource(), true); } + } - public void handleChange(ChangeEvent event) { + private class ChildStaleListener implements IStaleListener { + public void handleStale(StaleEvent event) { processStalenessChange((IObservable) event.getSource(), true); } } - private ChildListener childListener = new ChildListener(); + private IChangeListener childChangeListener = new ChildChangeListener(); + private IStaleListener childStaleListener = new ChildStaleListener(); /** * @param observables - * @param stalenessConsumer + * @param stalenessConsumer */ public StalenessTracker(IObservable[] observables, IStalenessConsumer stalenessConsumer) { @@ -85,9 +88,9 @@ public class StalenessTracker { * @param child */ private boolean getOldChildStale(IObservable child) { - Object oldChildValue = staleMap.get(child); - boolean oldChildStale = oldChildValue == null ? false - : ((Boolean) oldChildValue).booleanValue(); + Boolean oldChildValue = staleMap.get(child); + boolean oldChildStale = oldChildValue == null ? false : oldChildValue + .booleanValue(); return oldChildStale; } @@ -100,8 +103,8 @@ public class StalenessTracker { private void doAddObservable(IObservable observable, boolean callback) { processStalenessChange(observable, callback); - observable.addChangeListener(childListener); - observable.addStaleListener(childListener); + observable.addChangeListener(childChangeListener); + observable.addStaleListener(childStaleListener); } /** @@ -114,8 +117,8 @@ public class StalenessTracker { staleCount--; } staleMap.remove(observable); - observable.removeChangeListener(childListener); - observable.removeStaleListener(childListener); + observable.removeChangeListener(childChangeListener); + observable.removeStaleListener(childStaleListener); boolean newStale = staleCount > 0; if (newStale != oldStale) { stalenessConsumer.setStale(newStale); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableList.java index 6a11d682..960aa60c 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableList.java @@ -24,17 +24,19 @@ import org.eclipse.core.databinding.observable.list.IObservableList; /** * ObservableList implementation that prevents modification by consumers. Events * in the originating wrapped list are propagated and thrown from this instance - * when appropriate. All mutators throw an UnsupportedOperationException. + * when appropriate. All mutators throw an UnsupportedOperationException. + * + * @param <E> * * @since 1.0 */ -public class UnmodifiableObservableList extends DecoratingObservableList { - private List unmodifiableList; +public class UnmodifiableObservableList<E> extends DecoratingObservableList<E> { + private List<E> unmodifiableList; /** * @param decorated */ - public UnmodifiableObservableList(IObservableList decorated) { + public UnmodifiableObservableList(IObservableList<E> decorated) { super(decorated, false); this.unmodifiableList = Collections.unmodifiableList(decorated); } @@ -43,15 +45,15 @@ public class UnmodifiableObservableList extends DecoratingObservableList { throw new UnsupportedOperationException(); } - public boolean add(Object o) { + public boolean add(E o) { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { throw new UnsupportedOperationException(); } @@ -59,25 +61,25 @@ public class UnmodifiableObservableList extends DecoratingObservableList { throw new UnsupportedOperationException(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); return unmodifiableList.iterator(); } - public ListIterator listIterator() { + public ListIterator<E> listIterator() { return listIterator(0); } - public ListIterator listIterator(int index) { + public ListIterator<E> listIterator(int index) { getterCalled(); return unmodifiableList.listIterator(index); } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { throw new UnsupportedOperationException(); } - public Object remove(int index) { + public E remove(int index) { throw new UnsupportedOperationException(); } @@ -85,19 +87,19 @@ public class UnmodifiableObservableList extends DecoratingObservableList { throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public Object set(int index, Object element) { + public E set(int index, E element) { throw new UnsupportedOperationException(); } - public List subList(int fromIndex, int toIndex) { + public List<E> subList(int fromIndex, int toIndex) { getterCalled(); return unmodifiableList.subList(fromIndex, toIndex); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableMap.java index ac6beb22..da72583a 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableMap.java @@ -24,15 +24,19 @@ import org.eclipse.core.databinding.observable.map.IObservableMap; * in the originating wrapped map are propagated and thrown from this instance * when appropriate. All mutators throw an UnsupportedOperationException. * + * @param <K> + * @param <V> + * * @since 1.0 */ -public class UnmodifiableObservableMap extends DecoratingObservableMap { - Map unmodifiableMap; +public class UnmodifiableObservableMap<K, V> extends + DecoratingObservableMap<K, V> { + Map<K, V> unmodifiableMap; /** * @param decorated */ - public UnmodifiableObservableMap(IObservableMap decorated) { + public UnmodifiableObservableMap(IObservableMap<K, V> decorated) { super(decorated, false); this.unmodifiableMap = Collections.unmodifiableMap(decorated); } @@ -41,29 +45,29 @@ public class UnmodifiableObservableMap extends DecoratingObservableMap { throw new UnsupportedOperationException(); } - public Set entrySet() { + public Set<Entry<K, V>> entrySet() { getterCalled(); return unmodifiableMap.entrySet(); } - public Set keySet() { + public Set<K> keySet() { getterCalled(); return unmodifiableMap.keySet(); } - public Object put(Object key, Object value) { + public V put(K key, V value) { throw new UnsupportedOperationException(); } - public void putAll(Map m) { + public void putAll(Map<? extends K, ? extends V> m) { throw new UnsupportedOperationException(); } - public Object remove(Object key) { + public V remove(Object key) { throw new UnsupportedOperationException(); } - public Collection values() { + public Collection<V> values() { getterCalled(); return unmodifiableMap.values(); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableSet.java index b367c03e..a8dba557 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableSet.java @@ -27,15 +27,17 @@ import org.eclipse.core.databinding.observable.set.IObservableSet; * in the originating wrapped list are propagated and thrown from this instance * when appropriate. All mutators throw an UnsupportedOperationException. * + * @param <E> + * * @since 1.1 */ -public class UnmodifiableObservableSet extends DecoratingObservableSet { - private Set unmodifiableSet; +public class UnmodifiableObservableSet<E> extends DecoratingObservableSet<E> { + private Set<E> unmodifiableSet; /** * @param decorated */ - public UnmodifiableObservableSet(IObservableSet decorated) { + public UnmodifiableObservableSet(IObservableSet<E> decorated) { super(decorated, false); this.unmodifiableSet = Collections.unmodifiableSet(decorated); @@ -45,7 +47,7 @@ public class UnmodifiableObservableSet extends DecoratingObservableSet { throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } @@ -53,7 +55,7 @@ public class UnmodifiableObservableSet extends DecoratingObservableSet { throw new UnsupportedOperationException(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); return unmodifiableSet.iterator(); } @@ -62,11 +64,11 @@ public class UnmodifiableObservableSet extends DecoratingObservableSet { throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java index ae7ed178..9f72511d 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java @@ -18,9 +18,13 @@ import org.eclipse.core.databinding.observable.value.IObservableValue; /** * An unmodifiable wrapper class for IObservableValue instances. + * + * @param <T> + * * @since 1.1 */ -public class UnmodifiableObservableValue extends DecoratingObservableValue { +public class UnmodifiableObservableValue<T> extends + DecoratingObservableValue<T> { /** * Constructs an UnmodifiableObservableValue which wraps the given * observable value @@ -28,11 +32,11 @@ public class UnmodifiableObservableValue extends DecoratingObservableValue { * @param wrappedValue * the observable value to wrap in an unmodifiable instance. */ - public UnmodifiableObservableValue(IObservableValue wrappedValue) { + public UnmodifiableObservableValue(IObservableValue<T> wrappedValue) { super(wrappedValue, false); } - public void setValue(Object value) { + public void setValue(T value) { throw new UnsupportedOperationException(); } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableList.java index f3fc9464..6868ad65 100755 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableList.java @@ -34,29 +34,34 @@ import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.runtime.Assert; /** + * @param <M> + * type of the master observable + * @param <E> + * type of the elements in the inner observable list * @since 3.2 * */ -public class DetailObservableList extends ObservableList implements IObserving { +public class DetailObservableList<M, E> extends ObservableList<E> implements + IObserving { private boolean updating = false; - private IListChangeListener innerChangeListener = new IListChangeListener() { - public void handleListChange(ListChangeEvent event) { + private IListChangeListener<E> innerChangeListener = new IListChangeListener<E>() { + public void handleListChange(ListChangeEvent<E> event) { if (!updating) { fireListChange(event.diff); } } }; - private Object currentOuterValue; + private M currentOuterValue; - private IObservableList innerObservableList; + private IObservableList<E> innerObservableList; - private IObservableFactory factory; + private IObservableFactory<? super M, IObservableList<E>> factory; - private IObservableValue outerObservableValue; + private IObservableValue<M> outerObservableValue; private Object detailType; @@ -65,9 +70,10 @@ public class DetailObservableList extends ObservableList implements IObserving { * @param outerObservableValue * @param detailType */ - public DetailObservableList(IObservableFactory factory, - IObservableValue outerObservableValue, Object detailType) { - super(outerObservableValue.getRealm(), Collections.EMPTY_LIST, + public DetailObservableList( + IObservableFactory<? super M, IObservableList<E>> factory, + IObservableValue<M> outerObservableValue, Object detailType) { + super(outerObservableValue.getRealm(), Collections.<E> emptyList(), detailType); Assert.isTrue(!outerObservableValue.isDisposed(), "Master observable is disposed"); //$NON-NLS-1$ @@ -91,13 +97,13 @@ public class DetailObservableList extends ObservableList implements IObserving { outerObservableValue.addValueChangeListener(outerChangeListener); } - IValueChangeListener outerChangeListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + IValueChangeListener<M> outerChangeListener = new IValueChangeListener<M>() { + public void handleValueChange(ValueChangeEvent<M> event) { if (isDisposed()) return; ObservableTracker.setIgnore(true); try { - List oldList = new ArrayList(wrappedList); + List<E> oldList = new ArrayList<E>(wrappedList); updateInnerObservableList(); fireListChange(Diffs.computeListDiff(oldList, wrappedList)); } finally { @@ -114,11 +120,11 @@ public class DetailObservableList extends ObservableList implements IObserving { currentOuterValue = outerObservableValue.getValue(); if (currentOuterValue == null) { innerObservableList = null; - wrappedList = Collections.EMPTY_LIST; + wrappedList = Collections.emptyList(); } else { ObservableTracker.setIgnore(true); try { - innerObservableList = (IObservableList) factory + innerObservableList = factory .createObservable(currentOuterValue); } finally { ObservableTracker.setIgnore(false); @@ -136,7 +142,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public boolean add(final Object o) { + public boolean add(final E o) { ObservableTracker.setIgnore(true); try { return wrappedList.add(o); @@ -145,7 +151,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public void add(final int index, final Object element) { + public void add(final int index, final E element) { ObservableTracker.setIgnore(true); try { wrappedList.add(index, element); @@ -163,7 +169,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public Object set(final int index, final Object element) { + public E set(final int index, final E element) { ObservableTracker.setIgnore(true); try { return wrappedList.set(index, element); @@ -172,7 +178,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public Object move(final int oldIndex, final int newIndex) { + public E move(final int oldIndex, final int newIndex) { if (innerObservableList != null) { ObservableTracker.setIgnore(true); try { @@ -184,7 +190,7 @@ public class DetailObservableList extends ObservableList implements IObserving { return super.move(oldIndex, newIndex); } - public Object remove(final int index) { + public E remove(final int index) { ObservableTracker.setIgnore(true); try { return wrappedList.remove(index); @@ -193,7 +199,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public boolean addAll(final Collection c) { + public boolean addAll(final Collection<? extends E> c) { ObservableTracker.setIgnore(true); try { return wrappedList.addAll(c); @@ -202,7 +208,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public boolean addAll(final int index, final Collection c) { + public boolean addAll(final int index, final Collection<? extends E> c) { ObservableTracker.setIgnore(true); try { return wrappedList.addAll(index, c); @@ -211,7 +217,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public boolean removeAll(final Collection c) { + public boolean removeAll(final Collection<?> c) { ObservableTracker.setIgnore(true); try { return wrappedList.removeAll(c); @@ -220,7 +226,7 @@ public class DetailObservableList extends ObservableList implements IObserving { } } - public boolean retainAll(final Collection c) { + public boolean retainAll(final Collection<?> c) { ObservableTracker.setIgnore(true); try { return wrappedList.retainAll(c); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableMap.java index fbfc9d3e..9a489fb3 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableMap.java @@ -33,27 +33,34 @@ import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.runtime.Assert; /** + * @param <M> + * type of the master observable + * @param <K> + * type of the keys to the inner observable map + * @param <V> + * type of the values in the inner observable map * @since 1.1 * */ -public class DetailObservableMap extends ObservableMap implements IObserving { +public class DetailObservableMap<M, K, V> extends ObservableMap<K, V> implements + IObserving { private boolean updating = false; - private IObservableValue master; - private IObservableFactory detailFactory; + private IObservableValue<M> master; + private IObservableFactory<? super M, IObservableMap<K, V>> detailFactory; - private IObservableMap detailMap; + private IObservableMap<K, V> detailMap; private Object detailKeyType; private Object detailValueType; - private IValueChangeListener masterChangeListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + private IValueChangeListener<M> masterChangeListener = new IValueChangeListener<M>() { + public void handleValueChange(ValueChangeEvent<M> event) { if (isDisposed()) return; ObservableTracker.setIgnore(true); try { - Map oldMap = new HashMap(wrappedMap); + Map<K, V> oldMap = new HashMap<K, V>(wrappedMap); updateDetailMap(); fireMapChange(Diffs.computeMapDiff(oldMap, wrappedMap)); } finally { @@ -62,8 +69,8 @@ public class DetailObservableMap extends ObservableMap implements IObserving { } }; - private IMapChangeListener detailChangeListener = new IMapChangeListener() { - public void handleMapChange(MapChangeEvent event) { + private IMapChangeListener<K, V> detailChangeListener = new IMapChangeListener<K, V>() { + public void handleMapChange(MapChangeEvent<K, V> event) { if (!updating) { fireMapChange(event.diff); } @@ -81,9 +88,10 @@ public class DetailObservableMap extends ObservableMap implements IObserving { * @param valueType * */ - public DetailObservableMap(IObservableFactory detailFactory, - IObservableValue master, Object keyType, Object valueType) { - super(master.getRealm(), Collections.EMPTY_MAP); + public DetailObservableMap( + IObservableFactory<? super M, IObservableMap<K, V>> detailFactory, + IObservableValue<M> master, Object keyType, Object valueType) { + super(master.getRealm(), Collections.<K, V> emptyMap()); Assert.isTrue(!master.isDisposed(), "Master observable is disposed"); //$NON-NLS-1$ this.master = master; @@ -107,7 +115,7 @@ public class DetailObservableMap extends ObservableMap implements IObserving { } private void updateDetailMap() { - final Object masterValue = master.getValue(); + final M masterValue = master.getValue(); if (detailMap != null) { detailMap.removeMapChangeListener(detailChangeListener); detailMap.dispose(); @@ -115,17 +123,16 @@ public class DetailObservableMap extends ObservableMap implements IObserving { if (masterValue == null) { detailMap = null; - wrappedMap = Collections.EMPTY_MAP; + wrappedMap = Collections.emptyMap(); } else { ObservableTracker.setIgnore(true); try { - detailMap = (IObservableMap) detailFactory - .createObservable(masterValue); + detailMap = detailFactory.createObservable(masterValue); } finally { ObservableTracker.setIgnore(false); } - DetailObservableHelper.warnIfDifferentRealms(getRealm(), detailMap - .getRealm()); + DetailObservableHelper.warnIfDifferentRealms(getRealm(), + detailMap.getRealm()); wrappedMap = detailMap; if (detailKeyType != null) { @@ -154,7 +161,7 @@ public class DetailObservableMap extends ObservableMap implements IObserving { return detailValueType; } - public Object put(final Object key, final Object value) { + public V put(final K key, final V value) { ObservableTracker.setIgnore(true); try { return detailMap.put(key, value); @@ -163,7 +170,7 @@ public class DetailObservableMap extends ObservableMap implements IObserving { } } - public void putAll(final Map map) { + public void putAll(final Map<? extends K, ? extends V> map) { ObservableTracker.setIgnore(true); try { detailMap.putAll(map); @@ -172,7 +179,7 @@ public class DetailObservableMap extends ObservableMap implements IObserving { } } - public Object remove(final Object key) { + public V remove(final Object key) { ObservableTracker.setIgnore(true); try { return detailMap.remove(key); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableSet.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableSet.java index d218e2f8..24b05cd2 100755 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableSet.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableSet.java @@ -33,37 +33,43 @@ import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.runtime.Assert; /** + * @param <M> + * type of the master observable + * @param <E> + * type of the elements in the inner observable list * @since 3.2 * */ -public class DetailObservableSet extends ObservableSet implements IObserving { +public class DetailObservableSet<M, E> extends ObservableSet<E> implements + IObserving { private boolean updating = false; - private ISetChangeListener innerChangeListener = new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { + private ISetChangeListener<E> innerChangeListener = new ISetChangeListener<E>() { + public void handleSetChange(SetChangeEvent<E> event) { if (!updating) { fireSetChange(event.diff); } } }; - private Object currentOuterValue; + private M currentOuterValue; - private IObservableSet innerObservableSet; + private IObservableSet<E> innerObservableSet; - private IObservableValue outerObservableValue; + private IObservableValue<M> outerObservableValue; - private IObservableFactory factory; + private IObservableFactory<? super M, IObservableSet<E>> factory; /** * @param factory * @param outerObservableValue * @param detailType */ - public DetailObservableSet(IObservableFactory factory, - IObservableValue outerObservableValue, Object detailType) { - super(outerObservableValue.getRealm(), Collections.EMPTY_SET, + public DetailObservableSet( + IObservableFactory<? super M, IObservableSet<E>> factory, + IObservableValue<M> outerObservableValue, Object detailType) { + super(outerObservableValue.getRealm(), Collections.<E> emptySet(), detailType); Assert.isTrue(!outerObservableValue.isDisposed(), "Master observable is disposed"); //$NON-NLS-1$ @@ -72,7 +78,7 @@ public class DetailObservableSet extends ObservableSet implements IObserving { this.outerObservableValue = outerObservableValue; outerObservableValue.addDisposeListener(new IDisposeListener() { - public void handleDispose(DisposeEvent staleEvent) { + public void handleDispose(DisposeEvent disposeEvent) { dispose(); } }); @@ -86,13 +92,13 @@ public class DetailObservableSet extends ObservableSet implements IObserving { outerObservableValue.addValueChangeListener(outerChangeListener); } - IValueChangeListener outerChangeListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + IValueChangeListener<M> outerChangeListener = new IValueChangeListener<M>() { + public void handleValueChange(ValueChangeEvent<M> event) { if (isDisposed()) return; ObservableTracker.setIgnore(true); try { - Set oldSet = new HashSet(wrappedSet); + Set<E> oldSet = new HashSet<E>(wrappedSet); updateInnerObservableSet(); fireSetChange(Diffs.computeSetDiff(oldSet, wrappedSet)); } finally { @@ -109,11 +115,11 @@ public class DetailObservableSet extends ObservableSet implements IObserving { } if (currentOuterValue == null) { innerObservableSet = null; - wrappedSet = Collections.EMPTY_SET; + wrappedSet = Collections.emptySet(); } else { ObservableTracker.setIgnore(true); try { - innerObservableSet = (IObservableSet) factory + innerObservableSet = factory .createObservable(currentOuterValue); } finally { ObservableTracker.setIgnore(false); @@ -133,7 +139,7 @@ public class DetailObservableSet extends ObservableSet implements IObserving { } } - public boolean add(final Object o) { + public boolean add(final E o) { getterCalled(); ObservableTracker.setIgnore(true); try { @@ -153,7 +159,7 @@ public class DetailObservableSet extends ObservableSet implements IObserving { } } - public boolean addAll(final Collection c) { + public boolean addAll(final Collection<? extends E> c) { getterCalled(); ObservableTracker.setIgnore(true); try { @@ -163,7 +169,7 @@ public class DetailObservableSet extends ObservableSet implements IObserving { } } - public boolean removeAll(final Collection c) { + public boolean removeAll(final Collection<?> c) { getterCalled(); ObservableTracker.setIgnore(true); try { @@ -173,7 +179,7 @@ public class DetailObservableSet extends ObservableSet implements IObserving { } } - public boolean retainAll(final Collection c) { + public boolean retainAll(final Collection<?> c) { getterCalled(); ObservableTracker.setIgnore(true); try { diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableValue.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableValue.java index be548b1b..2da79189 100755 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableValue.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/DetailObservableValue.java @@ -26,39 +26,44 @@ import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.runtime.Assert; /** + * @param <M> + * type of the master observable + * @param <T> + * type of inner observable value * @since 1.0 * */ -public class DetailObservableValue extends AbstractObservableValue implements - IObserving { +public class DetailObservableValue<M, T> extends AbstractObservableValue<T> + implements IObserving { private boolean updating = false; - private IValueChangeListener innerChangeListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + private IValueChangeListener<T> innerChangeListener = new IValueChangeListener<T>() { + public void handleValueChange(ValueChangeEvent<T> event) { if (!updating) { fireValueChange(event.diff); } } }; - private Object currentOuterValue; + private M currentOuterValue; - private IObservableValue innerObservableValue; + private IObservableValue<T> innerObservableValue; private Object detailType; - private IObservableValue outerObservableValue; + private IObservableValue<M> outerObservableValue; - private IObservableFactory factory; + private IObservableFactory<? super M, IObservableValue<T>> factory; /** * @param outerObservableValue * @param factory * @param detailType */ - public DetailObservableValue(IObservableValue outerObservableValue, - IObservableFactory factory, Object detailType) { + public DetailObservableValue(IObservableValue<M> outerObservableValue, + IObservableFactory<? super M, IObservableValue<T>> factory, + Object detailType) { super(outerObservableValue.getRealm()); Assert.isTrue(!outerObservableValue.isDisposed(), "Master observable is disposed"); //$NON-NLS-1$ @@ -82,13 +87,13 @@ public class DetailObservableValue extends AbstractObservableValue implements outerObservableValue.addValueChangeListener(outerChangeListener); } - IValueChangeListener outerChangeListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + IValueChangeListener<M> outerChangeListener = new IValueChangeListener<M>() { + public void handleValueChange(ValueChangeEvent<M> event) { if (isDisposed()) return; ObservableTracker.setIgnore(true); try { - Object oldValue = doGetValue(); + T oldValue = doGetValue(); updateInnerObservableValue(); fireValueChange(Diffs.createValueDiff(oldValue, doGetValue())); } finally { @@ -108,7 +113,7 @@ public class DetailObservableValue extends AbstractObservableValue implements } else { ObservableTracker.setIgnore(true); try { - innerObservableValue = (IObservableValue) factory + innerObservableValue = factory .createObservable(currentOuterValue); } finally { ObservableTracker.setIgnore(false); @@ -118,16 +123,15 @@ public class DetailObservableValue extends AbstractObservableValue implements if (detailType != null) { Object innerValueType = innerObservableValue.getValueType(); - Assert - .isTrue( - detailType.equals(innerValueType), - "Cannot change value type in a nested observable value, from " + innerValueType + " to " + detailType); //$NON-NLS-1$ //$NON-NLS-2$ + Assert.isTrue( + detailType.equals(innerValueType), + "Cannot change value type in a nested observable value, from " + innerValueType + " to " + detailType); //$NON-NLS-1$ //$NON-NLS-2$ } innerObservableValue.addValueChangeListener(innerChangeListener); } } - public void doSetValue(final Object value) { + public void doSetValue(final T value) { if (innerObservableValue != null) { ObservableTracker.setIgnore(true); try { @@ -138,7 +142,7 @@ public class DetailObservableValue extends AbstractObservableValue implements } } - public Object doGetValue() { + public T doGetValue() { if (innerObservableValue == null) return null; ObservableTracker.setIgnore(true); diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/ListDetailValueObservableList.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/ListDetailValueObservableList.java index df985d8c..1ba65706 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/ListDetailValueObservableList.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/ListDetailValueObservableList.java @@ -16,11 +16,13 @@ import java.util.BitSet; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.RandomAccess; import org.eclipse.core.databinding.observable.Diffs; import org.eclipse.core.databinding.observable.DisposeEvent; import org.eclipse.core.databinding.observable.IDisposeListener; +import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.IObserving; import org.eclipse.core.databinding.observable.IStaleListener; import org.eclipse.core.databinding.observable.ObservableTracker; @@ -39,35 +41,39 @@ import org.eclipse.core.internal.databinding.identity.IdentityMap; import org.eclipse.core.internal.databinding.identity.IdentitySet; /** + * @param <M> + * type of the master observables in the master list + * @param <E> + * type of the detail elements * @since 1.4 */ -public class ListDetailValueObservableList extends AbstractObservableList - implements IObserving, RandomAccess { +public class ListDetailValueObservableList<M, E> extends + AbstractObservableList<E> implements IObserving, RandomAccess { - private IObservableList masterList; + private IObservableList<M> masterList; - private IObservableFactory detailFactory; + private IObservableFactory<? super M, IObservableValue<E>> detailFactory; private Object detailType; // The list of detail observables. - private ArrayList detailList; + private ArrayList<IObservableValue<E>> detailList; // Maps every master to a DetailEntry containing the detail observable. This // map is used to avoid that multiple detail observables are created for the // same master. - private IdentityMap masterDetailMap = new IdentityMap(); + private IdentityMap<M, DetailEntry<E>> masterDetailMap = new IdentityMap<M, DetailEntry<E>>(); - private IdentitySet staleDetailObservables = new IdentitySet(); + private IdentitySet<IObservable> staleDetailObservables = new IdentitySet<IObservable>(); - private IListChangeListener masterListListener = new IListChangeListener() { - public void handleListChange(ListChangeEvent event) { + private IListChangeListener<M> masterListListener = new IListChangeListener<M>() { + public void handleListChange(ListChangeEvent<M> event) { handleMasterListChange(event.diff); } }; - private IValueChangeListener detailValueListener = new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + private IValueChangeListener<E> detailValueListener = new IValueChangeListener<E>() { + public void handleValueChange(ValueChangeEvent<E> event) { if (!event.getObservable().isStale()) { staleDetailObservables.remove(event.getObservable()); } @@ -97,13 +103,14 @@ public class ListDetailValueObservableList extends AbstractObservableList * @param detailFactory * @param detailType */ - public ListDetailValueObservableList(IObservableList masterList, - IObservableFactory detailFactory, Object detailType) { + public ListDetailValueObservableList(IObservableList<M> masterList, + IObservableFactory<? super M, IObservableValue<E>> detailFactory, + Object detailType) { super(masterList.getRealm()); this.masterList = masterList; this.detailFactory = detailFactory; this.detailType = detailType; - this.detailList = new ArrayList(); + this.detailList = new ArrayList<IObservableValue<E>>(); // Add change/stale/dispose listeners on the master list. masterList.addListChangeListener(masterListListener); @@ -114,14 +121,15 @@ public class ListDetailValueObservableList extends AbstractObservableList } }); - ListDiff initMasterDiff = Diffs.computeListDiff(Collections.EMPTY_LIST, + List<M> emptyList = Collections.emptyList(); + ListDiff<M> initMasterDiff = Diffs.computeListDiff(emptyList, masterList); handleMasterListChange(initMasterDiff); } protected synchronized void firstListenerAdded() { for (int i = 0; i < detailList.size(); i++) { - IObservableValue detail = (IObservableValue) detailList.get(i); + IObservableValue<E> detail = detailList.get(i); detail.addValueChangeListener(detailValueListener); detail.addStaleListener(detailStaleListener); if (detail.isStale()) { @@ -136,25 +144,27 @@ public class ListDetailValueObservableList extends AbstractObservableList } for (int i = 0; i < detailList.size(); i++) { - IObservableValue detail = (IObservableValue) detailList.get(i); + IObservableValue<E> detail = detailList.get(i); detail.removeValueChangeListener(detailValueListener); detail.removeStaleListener(detailStaleListener); } staleDetailObservables.clear(); } - private void handleMasterListChange(ListDiff masterListDiff) { + private void handleMasterListChange(ListDiff<M> masterListDiff) { boolean wasStale = isStale(); boolean hasListeners = hasListeners(); - ListDiffEntry[] masterEntries = masterListDiff.getDifferences(); - ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; - for (int i = 0; i < masterEntries.length; i++) { - ListDiffEntry masterEntry = masterEntries[i]; + List<ListDiffEntry<M>> masterEntries = masterListDiff + .getDifferencesAsList(); + List<ListDiffEntry<E>> detailEntries = new ArrayList<ListDiffEntry<E>>( + masterEntries.size()); + for (int i = 0; i < masterEntries.size(); i++) { + ListDiffEntry<M> masterEntry = masterEntries.get(i); int index = masterEntry.getPosition(); - Object masterElement = masterEntry.getElement(); - Object detailValue; + M masterElement = masterEntry.getElement(); + E detailValue; if (masterEntry.isAddition()) { detailValue = addDetailObservable(masterElement, index); } else { @@ -163,8 +173,10 @@ public class ListDetailValueObservableList extends AbstractObservableList if (hasListeners) { // Create the corresponding diff for the detail list. - detailEntries[i] = Diffs.createListDiffEntry(index, - masterEntry.isAddition(), detailValue); + detailEntries.add(Diffs.createListDiffEntry(index, + masterEntry.isAddition(), detailValue)); + } else { + detailEntries.add(null); } } @@ -178,9 +190,8 @@ public class ListDetailValueObservableList extends AbstractObservableList } } - private Object addDetailObservable(Object masterElement, int index) { - DetailEntry detailEntry = (DetailEntry) masterDetailMap - .get(masterElement); + private E addDetailObservable(M masterElement, int index) { + DetailEntry<E> detailEntry = masterDetailMap.get(masterElement); if (detailEntry != null) { // If we already have a detail observable for the given // masterElement, we increment the reference count. @@ -189,8 +200,8 @@ public class ListDetailValueObservableList extends AbstractObservableList return detailEntry.detailObservable.getValue(); } - IObservableValue detail = createDetailObservable(masterElement); - masterDetailMap.put(masterElement, new DetailEntry(detail)); + IObservableValue<E> detail = createDetailObservable(masterElement); + masterDetailMap.put(masterElement, new DetailEntry<E>(detail)); detailList.add(index, detail); @@ -205,14 +216,13 @@ public class ListDetailValueObservableList extends AbstractObservableList return detail.getValue(); } - private Object removeDetailObservable(Object masterElement, int index) { - IObservableValue detail = (IObservableValue) detailList.remove(index); - Object detailValue = detail.getValue(); + private E removeDetailObservable(Object masterElement, int index) { + IObservableValue<E> detail = detailList.remove(index); + E detailValue = detail.getValue(); - DetailEntry detailEntry = (DetailEntry) masterDetailMap - .get(masterElement); + DetailEntry<E> detailEntry = masterDetailMap.get(masterElement); - // We may only dispose the detail observable ASA there are no more + // We may only dispose the detail observable when there are no more // masters referencing it. detailEntry.masterReferenceCount--; if (detailEntry.masterReferenceCount == 0) { @@ -224,8 +234,8 @@ public class ListDetailValueObservableList extends AbstractObservableList return detailValue; } - private void handleDetailValueChange(ValueChangeEvent event) { - IObservableValue detail = event.getObservableValue(); + private void handleDetailValueChange(ValueChangeEvent<E> event) { + IObservableValue<E> detail = event.getObservableValue(); // When we get a change event on a detail observable, we must find its // position while there may also be duplicate entries. @@ -237,26 +247,22 @@ public class ListDetailValueObservableList extends AbstractObservableList } // Create the diff for every found position. - Object oldValue = event.diff.getOldValue(); - Object newValue = event.diff.getNewValue(); - ListDiffEntry[] diffEntries = new ListDiffEntry[2 * detailIndexes - .cardinality()]; - int diffIndex = 0; + E oldValue = event.diff.getOldValue(); + E newValue = event.diff.getNewValue(); + List<ListDiffEntry<E>> diffEntries = new ArrayList<ListDiffEntry<E>>( + 2 * detailIndexes.cardinality()); for (int b = detailIndexes.nextSetBit(0); b != -1; b = detailIndexes .nextSetBit(b + 1)) { - diffEntries[diffIndex++] = Diffs.createListDiffEntry(b, false, - oldValue); - diffEntries[diffIndex++] = Diffs.createListDiffEntry(b, true, - newValue); + diffEntries.add(Diffs.createListDiffEntry(b, false, oldValue)); + diffEntries.add(Diffs.createListDiffEntry(b, true, newValue)); } fireListChange(Diffs.createListDiff(diffEntries)); } - private IObservableValue createDetailObservable(Object masterElement) { + private IObservableValue<E> createDetailObservable(M masterElement) { ObservableTracker.setIgnore(true); try { - return (IObservableValue) detailFactory - .createObservable(masterElement); + return detailFactory.createObservable(masterElement); } finally { ObservableTracker.setIgnore(false); } @@ -266,19 +272,19 @@ public class ListDetailValueObservableList extends AbstractObservableList return detailList.size(); } - public Object get(int index) { + public E get(int index) { ObservableTracker.getterCalled(this); - return ((IObservableValue) detailList.get(index)).getValue(); + return detailList.get(index).getValue(); } - public Object set(int index, Object element) { - IObservableValue detail = (IObservableValue) detailList.get(index); - Object oldElement = detail.getValue(); + public E set(int index, E element) { + IObservableValue<E> detail = detailList.get(index); + E oldElement = detail.getValue(); detail.setValue(element); return oldElement; } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { throw new UnsupportedOperationException(); } @@ -286,11 +292,11 @@ public class ListDetailValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -320,8 +326,9 @@ public class ListDetailValueObservableList extends AbstractObservableList } if (detailList != null) { - for (Iterator iter = detailList.iterator(); iter.hasNext();) { - IObservableValue detailValue = (IObservableValue) iter.next(); + for (Iterator<IObservableValue<E>> iter = detailList.iterator(); iter + .hasNext();) { + IObservableValue<E> detailValue = iter.next(); detailValue.dispose(); } detailList.clear(); @@ -338,13 +345,13 @@ public class ListDetailValueObservableList extends AbstractObservableList super.dispose(); } - private static final class DetailEntry { + private static final class DetailEntry<E> { - private final IObservableValue detailObservable; + private final IObservableValue<E> detailObservable; private int masterReferenceCount = 1; - public DetailEntry(IObservableValue detailObservable) { + public DetailEntry(IObservableValue<E> detailObservable) { this.detailObservable = detailObservable; } } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/MapDetailValueObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/MapDetailValueObservableMap.java index fc3cec11..f3318ad6 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/MapDetailValueObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/MapDetailValueObservableMap.java @@ -39,25 +39,35 @@ import org.eclipse.core.internal.databinding.identity.IdentitySet; import org.eclipse.core.internal.databinding.observable.Util; /** + * @param <K> + * type of the keys (the keys to both the given master observable map + * and the keys to the returned detail map, both of which are the + * same set of keys) + * @param <M> + * type of the master observables in the master set, being the values + * of the given master observable map + * @param <E> + * type of the detail elements, being the values of the returned + * detail map * @since 1.4 */ -public class MapDetailValueObservableMap extends AbstractObservableMap - implements IObserving { +public class MapDetailValueObservableMap<K, M, E> extends + AbstractObservableMap<K, E> implements IObserving { - private IObservableMap masterMap; + private IObservableMap<K, M> masterMap; - private IObservableFactory observableValueFactory; + private IObservableFactory<? super M, IObservableValue<E>> observableValueFactory; private Object detailValueType; - private Set entrySet; + private Set<Map.Entry<K, E>> entrySet; - private IdentityHashMap keyDetailMap = new IdentityHashMap(); + private IdentityHashMap<K, IObservableValue<E>> keyDetailMap = new IdentityHashMap<K, IObservableValue<E>>(); - private IdentitySet staleDetailObservables = new IdentitySet(); + private IdentitySet<IObservableValue<E>> staleDetailObservables = new IdentitySet<IObservableValue<E>>(); - private IMapChangeListener masterMapListener = new IMapChangeListener() { - public void handleMapChange(MapChangeEvent event) { + private IMapChangeListener<K, M> masterMapListener = new IMapChangeListener<K, M>() { + public void handleMapChange(MapChangeEvent<K, M> event) { handleMasterMapChange(event.diff); } }; @@ -80,8 +90,10 @@ public class MapDetailValueObservableMap extends AbstractObservableMap * @param observableValueFactory * @param detailValueType */ - public MapDetailValueObservableMap(IObservableMap masterMap, - IObservableFactory observableValueFactory, Object detailValueType) { + public MapDetailValueObservableMap( + IObservableMap<K, M> masterMap, + IObservableFactory<? super M, IObservableValue<E>> observableValueFactory, + Object detailValueType) { super(masterMap.getRealm()); this.masterMap = masterMap; this.observableValueFactory = observableValueFactory; @@ -97,37 +109,38 @@ public class MapDetailValueObservableMap extends AbstractObservableMap }); // Initialize the map with the current state of the master map. - MapDiff initMasterDiff = Diffs.computeMapDiff(Collections.EMPTY_MAP, - masterMap); + Map<K, M> emptyMap = Collections.emptyMap(); + MapDiff<K, M> initMasterDiff = Diffs + .computeMapDiff(emptyMap, masterMap); handleMasterMapChange(initMasterDiff); } - private void handleMasterMapChange(MapDiff diff) { + private void handleMasterMapChange(MapDiff<K, M> diff) { // Collect the detail values for the master values in the input diff. - IdentityMap oldValues = new IdentityMap(); - IdentityMap newValues = new IdentityMap(); + IdentityMap<K, E> oldValues = new IdentityMap<K, E>(); + IdentityMap<K, E> newValues = new IdentityMap<K, E>(); // Handle added master values. - Set addedKeys = diff.getAddedKeys(); - for (Iterator iter = addedKeys.iterator(); iter.hasNext();) { - Object addedKey = iter.next(); + Set<K> addedKeys = diff.getAddedKeys(); + for (Iterator<K> iter = addedKeys.iterator(); iter.hasNext();) { + K addedKey = iter.next(); // For added master values, we set up a new detail observable. addDetailObservable(addedKey); // Get the value of the created detail observable for the new diff. - IObservableValue detailValue = getDetailObservableValue(addedKey); + IObservableValue<E> detailValue = getDetailObservableValue(addedKey); newValues.put(addedKey, detailValue.getValue()); } // Handle removed master values. - Set removedKeys = diff.getRemovedKeys(); - for (Iterator iter = removedKeys.iterator(); iter.hasNext();) { - Object removedKey = iter.next(); + Set<K> removedKeys = diff.getRemovedKeys(); + for (Iterator<K> iter = removedKeys.iterator(); iter.hasNext();) { + K removedKey = iter.next(); // First of all, get the current detail value and add it to the set // of old values of the new diff. - IObservableValue detailValue = getDetailObservableValue(removedKey); + IObservableValue<E> detailValue = getDetailObservableValue(removedKey); oldValues.put(removedKey, detailValue.getValue()); // For removed master values, we dispose the detail observable. @@ -135,13 +148,13 @@ public class MapDetailValueObservableMap extends AbstractObservableMap } // Handle changed master values. - Set changedKeys = diff.getChangedKeys(); - for (Iterator iter = changedKeys.iterator(); iter.hasNext();) { - Object changedKey = iter.next(); + Set<K> changedKeys = diff.getChangedKeys(); + for (Iterator<K> iter = changedKeys.iterator(); iter.hasNext();) { + K changedKey = iter.next(); // Get the detail value prior to the change and add it to the set of // old values of the new diff. - IObservableValue oldDetailValue = getDetailObservableValue(changedKey); + IObservableValue<E> oldDetailValue = getDetailObservableValue(changedKey); oldValues.put(changedKey, oldDetailValue.getValue()); // Remove the old detail value for the old master value and add it @@ -150,7 +163,7 @@ public class MapDetailValueObservableMap extends AbstractObservableMap addDetailObservable(changedKey); // Get the new detail value and add it to the set of new values. - IObservableValue newDetailValue = getDetailObservableValue(changedKey); + IObservableValue<E> newDetailValue = getDetailObservableValue(changedKey); newValues.put(changedKey, newDetailValue.getValue()); } @@ -159,19 +172,18 @@ public class MapDetailValueObservableMap extends AbstractObservableMap oldValues, newValues)); } - private void addDetailObservable(final Object addedKey) { - Object masterElement = masterMap.get(addedKey); + private void addDetailObservable(final K addedKey) { + M masterElement = masterMap.get(addedKey); - IObservableValue detailValue = (IObservableValue) keyDetailMap - .get(addedKey); + IObservableValue<E> detailValue = keyDetailMap.get(addedKey); if (detailValue == null) { detailValue = createDetailObservable(masterElement); keyDetailMap.put(addedKey, detailValue); - detailValue.addValueChangeListener(new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + detailValue.addValueChangeListener(new IValueChangeListener<E>() { + public void handleValueChange(ValueChangeEvent<E> event) { if (!event.getObservableValue().isStale()) { staleDetailObservables.remove(event.getSource()); } @@ -189,11 +201,10 @@ public class MapDetailValueObservableMap extends AbstractObservableMap detailValue.addStaleListener(detailStaleListener); } - private IObservableValue createDetailObservable(Object masterElement) { + private IObservableValue<E> createDetailObservable(M masterElement) { ObservableTracker.setIgnore(true); try { - return (IObservableValue) observableValueFactory - .createObservable(masterElement); + return observableValueFactory.createObservable(masterElement); } finally { ObservableTracker.setIgnore(false); } @@ -204,17 +215,16 @@ public class MapDetailValueObservableMap extends AbstractObservableMap return; } - IObservableValue detailValue = (IObservableValue) keyDetailMap - .remove(removedKey); + IObservableValue<E> detailValue = keyDetailMap.remove(removedKey); staleDetailObservables.remove(detailValue); detailValue.dispose(); } - private IObservableValue getDetailObservableValue(Object masterKey) { - return (IObservableValue) keyDetailMap.get(masterKey); + private IObservableValue<E> getDetailObservableValue(Object masterKey) { + return keyDetailMap.get(masterKey); } - private void addStaleDetailObservable(IObservableValue detailObservable) { + private void addStaleDetailObservable(IObservableValue<E> detailObservable) { boolean wasStale = isStale(); staleDetailObservables.add(detailObservable); if (!wasStale) { @@ -222,30 +232,30 @@ public class MapDetailValueObservableMap extends AbstractObservableMap } } - public Set keySet() { + public Set<K> keySet() { getterCalled(); return masterMap.keySet(); } - public Object get(Object key) { + public E get(Object key) { getterCalled(); if (!containsKey(key)) { return null; } - IObservableValue detailValue = getDetailObservableValue(key); + IObservableValue<E> detailValue = getDetailObservableValue(key); return detailValue.getValue(); } - public Object put(Object key, Object value) { + public E put(K key, E value) { if (!containsKey(key)) { return null; } - IObservableValue detailValue = getDetailObservableValue(key); - Object oldValue = detailValue.getValue(); + IObservableValue<E> detailValue = getDetailObservableValue(key); + E oldValue = detailValue.getValue(); detailValue.setValue(value); return oldValue; } @@ -256,15 +266,15 @@ public class MapDetailValueObservableMap extends AbstractObservableMap return masterMap.containsKey(key); } - public Object remove(Object key) { + public E remove(Object key) { checkRealm(); if (!containsKey(key)) { return null; } - IObservableValue detailValue = getDetailObservableValue(key); - Object oldValue = detailValue.getValue(); + IObservableValue<E> detailValue = getDetailObservableValue(key); + E oldValue = detailValue.getValue(); masterMap.remove(key); @@ -303,9 +313,9 @@ public class MapDetailValueObservableMap extends AbstractObservableMap } if (keyDetailMap != null) { - for (Iterator iter = keyDetailMap.values().iterator(); iter - .hasNext();) { - IObservableValue detailValue = (IObservableValue) iter.next(); + for (Iterator<IObservableValue<E>> iter = keyDetailMap.values() + .iterator(); iter.hasNext();) { + IObservableValue<E> detailValue = iter.next(); detailValue.dispose(); } keyDetailMap.clear(); @@ -322,7 +332,7 @@ public class MapDetailValueObservableMap extends AbstractObservableMap super.dispose(); } - public Set entrySet() { + public Set<Map.Entry<K, E>> entrySet() { getterCalled(); if (entrySet == null) { @@ -335,18 +345,18 @@ public class MapDetailValueObservableMap extends AbstractObservableMap ObservableTracker.getterCalled(this); } - private class EntrySet extends AbstractSet { + private class EntrySet extends AbstractSet<Map.Entry<K, E>> { - public Iterator iterator() { - final Iterator keyIterator = keySet().iterator(); - return new Iterator() { + public Iterator<Map.Entry<K, E>> iterator() { + final Iterator<K> keyIterator = keySet().iterator(); + return new Iterator<Map.Entry<K, E>>() { public boolean hasNext() { return keyIterator.hasNext(); } - public Object next() { - Object key = keyIterator.next(); + public Map.Entry<K, E> next() { + K key = keyIterator.next(); return new MapEntry(key); } @@ -361,24 +371,24 @@ public class MapDetailValueObservableMap extends AbstractObservableMap } } - private final class MapEntry implements Map.Entry { + private final class MapEntry implements Map.Entry<K, E> { - private final Object key; + private final K key; - private MapEntry(Object key) { + private MapEntry(K key) { this.key = key; } - public Object getKey() { + public K getKey() { MapDetailValueObservableMap.this.getterCalled(); return key; } - public Object getValue() { + public E getValue() { return MapDetailValueObservableMap.this.get(getKey()); } - public Object setValue(Object value) { + public E setValue(E value) { return MapDetailValueObservableMap.this.put(getKey(), value); } @@ -390,7 +400,7 @@ public class MapDetailValueObservableMap extends AbstractObservableMap return false; if (!(o instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) o; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) o; return Util.equals(this.getKey(), that.getKey()) && Util.equals(this.getValue(), that.getValue()); } diff --git a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/SetDetailValueObservableMap.java b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/SetDetailValueObservableMap.java index f66a1c9f..e92472d9 100644 --- a/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/SetDetailValueObservableMap.java +++ b/bundles/org.eclipse.core.databinding.observable/src/org/eclipse/core/internal/databinding/observable/masterdetail/SetDetailValueObservableMap.java @@ -27,20 +27,24 @@ import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.core.internal.databinding.identity.IdentitySet; /** + * @param <M> + * type of the master observables in the master set + * @param <E> + * type of the detail elements * @since 1.4 */ -public class SetDetailValueObservableMap extends ComputedObservableMap - implements IObserving { +public class SetDetailValueObservableMap<M, E> extends + ComputedObservableMap<M, E> implements IObserving { - private IObservableFactory observableValueFactory; + private IObservableFactory<? super M, IObservableValue<E>> observableValueFactory; - private Map detailObservableValueMap = new HashMap(); + private Map<M, IObservableValue<E>> detailObservableValueMap = new HashMap<M, IObservableValue<E>>(); - private IdentitySet staleDetailObservables = new IdentitySet(); + private IdentitySet<IObservableValue<?>> staleDetailObservables = new IdentitySet<IObservableValue<?>>(); private IStaleListener detailStaleListener = new IStaleListener() { public void handleStale(StaleEvent staleEvent) { - addStaleDetailObservable((IObservableValue) staleEvent + addStaleDetailObservable((IObservableValue<?>) staleEvent .getObservable()); } }; @@ -50,17 +54,19 @@ public class SetDetailValueObservableMap extends ComputedObservableMap * @param observableValueFactory * @param detailValueType */ - public SetDetailValueObservableMap(IObservableSet masterKeySet, - IObservableFactory observableValueFactory, Object detailValueType) { + public SetDetailValueObservableMap( + IObservableSet<M> masterKeySet, + IObservableFactory<? super M, IObservableValue<E>> observableValueFactory, + Object detailValueType) { super(masterKeySet, detailValueType); this.observableValueFactory = observableValueFactory; } - protected void hookListener(final Object addedKey) { - final IObservableValue detailValue = getDetailObservableValue(addedKey); + protected void hookListener(final M addedKey) { + final IObservableValue<E> detailValue = getDetailObservableValue(addedKey); - detailValue.addValueChangeListener(new IValueChangeListener() { - public void handleValueChange(ValueChangeEvent event) { + detailValue.addValueChangeListener(new IValueChangeListener<E>() { + public void handleValueChange(ValueChangeEvent<E> event) { if (!event.getObservableValue().isStale()) { staleDetailObservables.remove(detailValue); } @@ -78,36 +84,36 @@ public class SetDetailValueObservableMap extends ComputedObservableMap return; } - IObservableValue detailValue = (IObservableValue) detailObservableValueMap + IObservableValue<E> detailValue = detailObservableValueMap .remove(removedKey); staleDetailObservables.remove(detailValue); detailValue.dispose(); } - private IObservableValue getDetailObservableValue(Object masterKey) { - IObservableValue detailValue = (IObservableValue) detailObservableValueMap + private IObservableValue<E> getDetailObservableValue(M masterKey) { + IObservableValue<E> detailValue = detailObservableValueMap .get(masterKey); if (detailValue == null) { ObservableTracker.setIgnore(true); try { - detailValue = (IObservableValue) observableValueFactory + detailValue = observableValueFactory .createObservable(masterKey); - } finally { - ObservableTracker.setIgnore(false); - } - detailObservableValueMap.put(masterKey, detailValue); + detailObservableValueMap.put(masterKey, detailValue); - if (detailValue.isStale()) { - addStaleDetailObservable(detailValue); + if (detailValue.isStale()) { + addStaleDetailObservable(detailValue); + } + } finally { + ObservableTracker.setIgnore(false); } } return detailValue; } - private void addStaleDetailObservable(IObservableValue detailObservable) { + private void addStaleDetailObservable(IObservableValue<?> detailObservable) { boolean wasStale = isStale(); staleDetailObservables.add(detailObservable); if (!wasStale) { @@ -115,14 +121,14 @@ public class SetDetailValueObservableMap extends ComputedObservableMap } } - protected Object doGet(Object key) { - IObservableValue detailValue = getDetailObservableValue(key); + protected E doGet(M key) { + IObservableValue<E> detailValue = getDetailObservableValue(key); return detailValue.getValue(); } - protected Object doPut(Object key, Object value) { - IObservableValue detailValue = getDetailObservableValue(key); - Object oldValue = detailValue.getValue(); + protected E doPut(M key, E value) { + IObservableValue<E> detailValue = getDetailObservableValue(key); + E oldValue = detailValue.getValue(); detailValue.setValue(value); return oldValue; } @@ -133,15 +139,15 @@ public class SetDetailValueObservableMap extends ComputedObservableMap return keySet().contains(key); } - public Object remove(Object key) { + public E remove(Object key) { checkRealm(); if (!containsKey(key)) { return null; } - IObservableValue detailValue = getDetailObservableValue(key); - Object oldValue = detailValue.getValue(); + IObservableValue<E> detailValue = getDetailObservableValue((M) key); + E oldValue = detailValue.getValue(); keySet().remove(key); diff --git a/bundles/org.eclipse.core.databinding.property/.classpath b/bundles/org.eclipse.core.databinding.property/.classpath index 6f3b481a..64c5e31b 100644 --- a/bundles/org.eclipse.core.databinding.property/.classpath +++ b/bundles/org.eclipse.core.databinding.property/.classpath @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/CDC-1.1%Foundation-1.1"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="src" path="src"/> <classpathentry kind="output" path="bin"/> diff --git a/bundles/org.eclipse.core.databinding.property/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.core.databinding.property/.settings/org.eclipse.jdt.core.prefs index 9e52c974..b0aff68d 100644 --- a/bundles/org.eclipse.core.databinding.property/.settings/org.eclipse.jdt.core.prefs +++ b/bundles/org.eclipse.core.databinding.property/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,3 @@ -#Thu Feb 05 11:35:38 MST 2009 eclipse.preferences.version=1 org.eclipse.jdt.core.builder.cleanOutputFolder=clean org.eclipse.jdt.core.builder.duplicateResourceTask=warning @@ -17,9 +16,9 @@ org.eclipse.jdt.core.codeComplete.localSuffixes= org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.4 +org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate @@ -96,7 +95,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enab org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning -org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 diff --git a/bundles/org.eclipse.core.databinding.property/META-INF/MANIFEST.MF b/bundles/org.eclipse.core.databinding.property/META-INF/MANIFEST.MF index b2124d5f..c5651d76 100644 --- a/bundles/org.eclipse.core.databinding.property/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.core.databinding.property/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.core.databinding.property -Bundle-Version: 1.4.200.qualifier +Bundle-Version: 1.5.0.qualifier Bundle-ClassPath: . Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/INativePropertyListener.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/INativePropertyListener.java index a46b83cf..b8eb9c49 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/INativePropertyListener.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/INativePropertyListener.java @@ -23,6 +23,8 @@ import org.eclipse.core.databinding.property.value.SimpleValueProperty; * source objects are parlayed to the {@link ISimplePropertyListener} provided * to the method that constructed this native listener instance. * + * @param <S> + * type of the source object * @since 1.2 * @see NativePropertyListener * @see SimpleValueProperty#adaptListener(ISimplePropertyListener) @@ -30,7 +32,7 @@ import org.eclipse.core.databinding.property.value.SimpleValueProperty; * @see SimpleSetProperty#adaptListener(ISimplePropertyListener) * @see SimpleMapProperty#adaptListener(ISimplePropertyListener) */ -public interface INativePropertyListener { +public interface INativePropertyListener<S> { /** * Adds the receiver as a listener for property events on the specified * property source. @@ -39,7 +41,7 @@ public interface INativePropertyListener { * the property source (may be null) * @noreference This method is not intended to be referenced by clients. */ - public void addTo(Object source); + public void addTo(S source); /** * Removes the receiver as a listener for property events on the specified @@ -49,5 +51,5 @@ public interface INativePropertyListener { * the property source (may be null) * @noreference This method is not intended to be referenced by clients. */ - public void removeFrom(Object source); + public void removeFrom(S source); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/IPropertyObservable.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/IPropertyObservable.java index e13084a0..8dfdda8a 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/IPropertyObservable.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/IPropertyObservable.java @@ -16,13 +16,15 @@ import org.eclipse.core.databinding.observable.IObserving; /** * Provides access to the details of property observables * + * @param <P> + * specific type of the value property being observed * @since 1.2 */ -public interface IPropertyObservable extends IObserving { +public interface IPropertyObservable<P extends IProperty> extends IObserving { /** * Returns the property being observed * * @return the property being observed */ - IProperty getProperty(); + P getProperty(); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/ISimplePropertyListener.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/ISimplePropertyListener.java index 1ca171d2..2d4b1621 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/ISimplePropertyListener.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/ISimplePropertyListener.java @@ -12,19 +12,23 @@ package org.eclipse.core.databinding.property; +import org.eclipse.core.databinding.observable.IDiff; + /** * Listener for changes to properties on a particular source object * + * @param <D> + * type of the diff handled by this listener * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. * @since 1.2 */ -public interface ISimplePropertyListener { +public interface ISimplePropertyListener<D extends IDiff> { /** * Handle the described property event. * * @param event * the event which occured */ - public void handleEvent(SimplePropertyEvent event); + public void handleEvent(SimplePropertyEvent<D> event); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/NativePropertyListener.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/NativePropertyListener.java index f0208ce9..a7dfc394 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/NativePropertyListener.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/NativePropertyListener.java @@ -16,11 +16,16 @@ import org.eclipse.core.databinding.observable.IDiff; /** * Abstract INativePropertyListener implementation * + * @param <S> + * type of the source object + * @param <D> + * type of the diff handled by this listener * @since 1.2 */ -public abstract class NativePropertyListener implements INativePropertyListener { +public abstract class NativePropertyListener<S, D extends IDiff> implements + INativePropertyListener<S> { private final IProperty property; - private final ISimplePropertyListener listener; + private final ISimplePropertyListener<D> listener; /** * Constructs a NativePropertyListener with the specified arguments @@ -31,24 +36,24 @@ public abstract class NativePropertyListener implements INativePropertyListener * the listener to receive property change notifications */ public NativePropertyListener(IProperty property, - ISimplePropertyListener listener) { + ISimplePropertyListener<D> listener) { this.property = property; this.listener = listener; } - public final void addTo(Object source) { + public final void addTo(S source) { if (source != null) doAddTo(source); } - protected abstract void doAddTo(Object source); + protected abstract void doAddTo(S source); - public final void removeFrom(Object source) { + public final void removeFrom(S source) { if (source != null) doRemoveFrom(source); } - protected abstract void doRemoveFrom(Object source); + protected abstract void doRemoveFrom(S source); /** * Notifies the listener that a property change occured on the source @@ -59,8 +64,8 @@ public abstract class NativePropertyListener implements INativePropertyListener * @param diff * a diff describing the change in state */ - protected void fireChange(Object source, IDiff diff) { - listener.handleEvent(new SimplePropertyEvent( + protected void fireChange(Object source, D diff) { + listener.handleEvent(new SimplePropertyEvent<D>( SimplePropertyEvent.CHANGE, source, property, diff)); } @@ -72,7 +77,7 @@ public abstract class NativePropertyListener implements INativePropertyListener * the source object whose property became stale */ protected void fireStale(Object source) { - listener.handleEvent(new SimplePropertyEvent(SimplePropertyEvent.STALE, - source, property, null)); + listener.handleEvent(new SimplePropertyEvent<D>( + SimplePropertyEvent.STALE, source, property, null)); } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/Properties.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/Properties.java index e5ed6048..3d77c29c 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/Properties.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/Properties.java @@ -12,6 +12,7 @@ package org.eclipse.core.databinding.property; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -37,24 +38,20 @@ import org.eclipse.core.internal.databinding.property.value.SelfValueProperty; * @since 1.2 */ public class Properties { + /** - * Returns an array of observable maps where each map observes the - * corresponding value property on all elements in the given domain set, for - * each property in the given array. - * * @param domainSet - * the set of elements whose properties will be observed * @param properties - * array of value properties to observe on each element in the - * domain set. * @return an array of observable maps where each map observes the - * corresponding value property of the given domain set. + * corresponding value property of the given domain set */ - public static IObservableMap[] observeEach(IObservableSet domainSet, - IValueProperty[] properties) { - IObservableMap[] maps = new IObservableMap[properties.length]; - for (int i = 0; i < maps.length; i++) + public static <S, E> IObservableMap<?, ?>[] observeEach( + IObservableSet<E> domainSet, + IValueProperty<? super E, ?>[] properties) { + IObservableMap<?, ?>[] maps = new IObservableMap[properties.length]; + for (int i = 0; i < maps.length; i++) { maps[i] = properties[i].observeDetail(domainSet); + } return maps; } @@ -73,16 +70,71 @@ public class Properties { * corresponding value property on all elements in the given domain * map's {@link Map#values() values} collection, for each property * in the given array. + * @since 1.5 */ - public static IObservableMap[] observeEach(IObservableMap domainMap, - IValueProperty[] properties) { - IObservableMap[] maps = new IObservableMap[properties.length]; + public static <S, E> IObservableMap<?, ?>[] observeEach( + IObservableMap<?, E> domainMap, + IValueProperty<? super E, ?>[] properties) { + IObservableMap<?, ?>[] maps = new IObservableMap[properties.length]; for (int i = 0; i < maps.length; i++) maps[i] = properties[i].observeDetail(domainMap); return maps; } /** + * Returns an array of observable maps where each map observes the + * corresponding value property on all elements in the given domain set, for + * each property in the given array. + * + * @param domainSet + * the set of elements whose properties will be observed + * @param properties + * array of value properties to observe on each element in the + * domain set + * @return an list of observable maps where each map observes the + * corresponding value property of the given domain set + * @since 1.5 + */ + public static <S, E> List<IObservableMap<E, ?>> observeEach( + IObservableSet<E> domainSet, + List<IValueProperty<? super E, ?>> properties) { + List<IObservableMap<E, ?>> maps = new ArrayList<IObservableMap<E, ?>>( + properties.size()); + for (IValueProperty<? super E, ?> property : properties) { + maps.add(property.observeDetail(domainSet)); + } + return maps; + } + + /** + * Returns an array of observable maps where each maps observes the + * corresponding value property on all elements in the given domain map's + * {@link Map#values() values} collection, for each property in the given + * array. + * + * @param domainMap + * the map of elements whose properties will be observed + * @param properties + * array of value properties to observe on each element in the + * domain map's {@link Map#values() values} collection + * @return a list of observable maps where each maps observes the + * corresponding value property on all elements in the given domain + * map's {@link Map#values() values} collection, for each property + * in the given array + * @since 1.5 + */ + public static <K, V> List<IObservableMap<K, ?>> observeEach( + IObservableMap<K, V> domainMap, + List<IValueProperty<? super V, ?>> properties) { + List<IObservableMap<K, ?>> maps = new ArrayList<IObservableMap<K, ?>>( + properties.size()); + for (IValueProperty<? super V, ?> property : properties) { + maps.add(property.observeDetail(domainMap)); + } + return maps; + } + + /** * Returns a value property which takes the source object itself as the * property value. This property may be used to wrap an object in an * unmodifiable {@link IObservableValue}. @@ -92,8 +144,8 @@ public class Properties { * @return a value property which takes the source object itself as the * property value. */ - public static IValueProperty selfValue(Object valueType) { - return new SelfValueProperty(valueType); + public static <T> IValueProperty<T, T> selfValue(T valueType) { + return new SelfValueProperty<T>(valueType); } /** @@ -106,8 +158,8 @@ public class Properties { * @return a list property which takes the source object (a {@link List}) as * the property list. */ - public static IListProperty selfList(Object elementType) { - return new SelfListProperty(elementType); + public static <E> IListProperty<List<E>, E> selfList(Object elementType) { + return new SelfListProperty<E>(elementType); } /** @@ -120,8 +172,8 @@ public class Properties { * @return a set property which takes the source object (a {@link Set}) as * the property set. */ - public static ISetProperty selfSet(Object elementType) { - return new SelfSetProperty(elementType); + public static <E> ISetProperty<Set<E>, E> selfSet(Object elementType) { + return new SelfSetProperty<E>(elementType); } /** @@ -136,8 +188,9 @@ public class Properties { * @return a map property which takes the source object (a {@link Map} as * the property map. */ - public static IMapProperty selfMap(Object keyType, Object valueType) { - return new SelfMapProperty(keyType, valueType); + public static <K, V> IMapProperty<Map<K, V>, K, V> selfMap(Object keyType, + Object valueType) { + return new SelfMapProperty<K, V>(keyType, valueType); } /** @@ -155,7 +208,8 @@ public class Properties { * @return a value property which observes the value of an * {@link IObservableValue}. */ - public static IValueProperty observableValue(Object valueType) { - return new ObservableValueProperty(valueType); + public static <T> IValueProperty<IObservableValue<T>, T> observableValue( + Object valueType) { + return new ObservableValueProperty<T>(valueType); } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/SimplePropertyEvent.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/SimplePropertyEvent.java index f811d2be..03aaec16 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/SimplePropertyEvent.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/SimplePropertyEvent.java @@ -20,9 +20,11 @@ import org.eclipse.core.internal.databinding.property.Util; /** * Event object events in the properties API * + * @param <D> + * type of the diff handled by this event * @since 1.2 */ -public final class SimplePropertyEvent extends EventObject { +public final class SimplePropertyEvent<D extends IDiff> extends EventObject { private static final long serialVersionUID = 1L; /** @@ -53,7 +55,7 @@ public final class SimplePropertyEvent extends EventObject { * If event == CHANGE, a diff object describing the change in state, or null * for an unknown change. */ - public final IDiff diff; + public final D diff; /** * Constructs a PropertyChangeEvent with the given attributes @@ -69,7 +71,7 @@ public final class SimplePropertyEvent extends EventObject { * is unknown or not applicable. */ public SimplePropertyEvent(int type, Object source, IProperty property, - IDiff diff) { + D diff) { super(source); this.type = type; this.property = property; @@ -84,7 +86,7 @@ public final class SimplePropertyEvent extends EventObject { if (getClass() != obj.getClass()) return false; - SimplePropertyEvent that = (SimplePropertyEvent) obj; + SimplePropertyEvent<?> that = (SimplePropertyEvent<?>) obj; return Util.equals(getSource(), that.getSource()) && Util.equals(this.property, that.property) && Util.equals(this.diff, that.diff); diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java index 103ab468..eca14a16 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/DelegatingListProperty.java @@ -22,11 +22,15 @@ import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; /** + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the list * @since 1.2 * */ -public abstract class DelegatingListProperty extends ListProperty { - private final IListProperty nullProperty; +public abstract class DelegatingListProperty<S, E> extends ListProperty<S, E> { + private final IListProperty<S, E> nullProperty; private final Object elementType; protected DelegatingListProperty() { @@ -47,10 +51,10 @@ public abstract class DelegatingListProperty extends ListProperty { * the property source (may be null) * @return the property to delegate to for the specified source object. */ - public final IListProperty getDelegate(Object source) { + public final IListProperty<S, E> getDelegate(S source) { if (source == null) return nullProperty; - IListProperty delegate = doGetDelegate(source); + IListProperty<S, E> delegate = doGetDelegate(source); if (delegate == null) delegate = nullProperty; return delegate; @@ -65,52 +69,52 @@ public abstract class DelegatingListProperty extends ListProperty { * the property source * @return the property to delegate to for the specified source object. */ - protected abstract IListProperty doGetDelegate(Object source); + protected abstract IListProperty<S, E> doGetDelegate(Object source); public Object getElementType() { return elementType; } - protected List doGetList(Object source) { + protected List<E> doGetList(S source) { return getDelegate(source).getList(source); } - protected void doSetList(Object source, List list) { + protected void doSetList(S source, List<E> list) { getDelegate(source).setList(source, list); } - protected void doUpdateList(Object source, ListDiff diff) { + protected void doUpdateList(S source, ListDiff<E> diff) { getDelegate(source).updateList(source, diff); } - public IObservableList observe(Object source) { + public IObservableList<E> observe(S source) { return getDelegate(source).observe(source); } - public IObservableList observe(Realm realm, Object source) { + public IObservableList<E> observe(Realm realm, S source) { return getDelegate(source).observe(realm, source); } - private class NullListProperty extends SimpleListProperty { + private class NullListProperty extends SimpleListProperty<S, E> { public Object getElementType() { return elementType; } - protected List doGetList(Object source) { - return Collections.EMPTY_LIST; + protected List<E> doGetList(S source) { + return Collections.emptyList(); } - protected void doSetList(Object source, List list, ListDiff diff) { + protected void doSetList(S source, List<E> list, ListDiff<E> diff) { } - protected void doSetList(Object source, List list) { + protected void doSetList(S source, List<E> list) { } - protected void doUpdateList(Object source, ListDiff diff) { + protected void doUpdateList(S source, ListDiff<E> diff) { } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<S> adaptListener( + ISimplePropertyListener<ListDiff<E>> listener) { return null; } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/IListProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/IListProperty.java index 7dc79b54..cb19347b 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/IListProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/IListProperty.java @@ -25,6 +25,10 @@ import org.eclipse.core.databinding.property.value.IValueProperty; /** * Interface for list-typed properties. * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the list * @since 1.2 * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that @@ -34,7 +38,7 @@ import org.eclipse.core.databinding.property.value.IValueProperty; * @see ListProperty * @see SimpleListProperty */ -public interface IListProperty extends IProperty { +public interface IListProperty<S, E> extends IProperty { /** * Returns the type of the elements in the collection or <code>null</code> * if untyped @@ -54,7 +58,7 @@ public interface IListProperty extends IProperty { * list property * @since 1.3 */ - public List getList(Object source); + public List<E> getList(S source); /** * Updates the property on the source with the specified change @@ -72,7 +76,7 @@ public interface IListProperty extends IProperty { * the new list * @since 1.3 */ - public void setList(Object source, List list); + public void setList(S source, List<E> list); /** * Updates the property on the source with the specified change @@ -89,7 +93,7 @@ public interface IListProperty extends IProperty { * a diff describing the change * @since 1.3 */ - public void updateList(Object source, ListDiff diff); + public void updateList(S source, ListDiff<E> diff); /** * Returns an observable list observing this list property on the given @@ -100,7 +104,7 @@ public interface IListProperty extends IProperty { * @return an observable list observing this list property on the given * property source */ - public IObservableList observe(Object source); + public IObservableList<E> observe(S source); /** * Returns an observable list observing this list property on the given @@ -113,7 +117,7 @@ public interface IListProperty extends IProperty { * @return an observable list observing this list property on the given * property source */ - public IObservableList observe(Realm realm, Object source); + public IObservableList<E> observe(Realm realm, S source); /** * Returns a factory for creating observable lists tracking this property of @@ -122,7 +126,7 @@ public interface IListProperty extends IProperty { * @return a factory for creating observable lists tracking this property of * a particular property source. */ - public IObservableFactory listFactory(); + public IObservableFactory<S, IObservableList<E>> listFactory(); /** * Returns a factory for creating observable lists in the given realm, @@ -134,7 +138,7 @@ public interface IListProperty extends IProperty { * @return a factory for creating observable lists in the given realm, * tracking this property of a particular property source. */ - public IObservableFactory listFactory(Realm realm); + public IObservableFactory<S, IObservableList<E>> listFactory(Realm realm); /** * Returns an observable list on the master observable's realm which tracks @@ -145,7 +149,8 @@ public interface IListProperty extends IProperty { * @return an observable list on the given realm which tracks this property * of the current value of <code>master</code>. */ - public IObservableList observeDetail(IObservableValue master); + public <U extends S> IObservableList<E> observeDetail( + IObservableValue<U> master); /** * Returns the nested combination of this property and the specified detail @@ -160,5 +165,6 @@ public interface IListProperty extends IProperty { * @return the nested combination of the master list and detail value * properties */ - public IListProperty values(IValueProperty detailValue); + public <T> IListProperty<S, T> values( + IValueProperty<? super E, T> detailValue); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/ListProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/ListProperty.java index cf9590b4..6a63ca2c 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/ListProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/ListProperty.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.List; import org.eclipse.core.databinding.observable.Diffs; -import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.ListDiff; @@ -31,9 +30,13 @@ import org.eclipse.core.internal.databinding.property.ListPropertyDetailValuesLi /** * Abstract implementation of IListProperty. * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the list * @since 1.2 */ -public abstract class ListProperty implements IListProperty { +public abstract class ListProperty<S, E> implements IListProperty<S, E> { /** * By default, this method returns <code>Collections.EMPTY_LIST</code> in @@ -49,9 +52,9 @@ public abstract class ListProperty implements IListProperty { * * @since 1.3 */ - public List getList(Object source) { + public List<E> getList(S source) { if (source == null) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } return Collections.unmodifiableList(doGetList(source)); } @@ -63,12 +66,12 @@ public abstract class ListProperty implements IListProperty { * the property source * @return a List with the current contents of the source's list property * @noreference This method is not intended to be referenced by clients. - * @since 1.3 + * @since 1.5 */ - protected List doGetList(Object source) { - IObservableList observable = observe(source); + protected List<E> doGetList(S source) { + IObservableList<E> observable = observe(source); try { - return new ArrayList(observable); + return new ArrayList<E>(observable); } finally { observable.dispose(); } @@ -77,7 +80,7 @@ public abstract class ListProperty implements IListProperty { /** * @since 1.3 */ - public final void setList(Object source, List list) { + public final void setList(S source, List<E> list) { if (source != null) { doSetList(source, list); } @@ -90,17 +93,17 @@ public abstract class ListProperty implements IListProperty { * the property source * @param list * the new list - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected void doSetList(Object source, List list) { + protected void doSetList(S source, List<E> list) { doUpdateList(source, Diffs.computeListDiff(doGetList(source), list)); } /** * @since 1.3 */ - public final void updateList(Object source, ListDiff diff) { + public final void updateList(S source, ListDiff<E> diff) { if (source != null) { doUpdateList(source, diff); } @@ -115,8 +118,8 @@ public abstract class ListProperty implements IListProperty { * a diff describing the change * @since 1.3 */ - protected void doUpdateList(Object source, ListDiff diff) { - IObservableList observable = observe(source); + protected void doUpdateList(S source, ListDiff<E> diff) { + IObservableList<E> observable = observe(source); try { diff.applyTo(observable); } finally { @@ -124,32 +127,35 @@ public abstract class ListProperty implements IListProperty { } } - public IObservableList observe(Object source) { + public IObservableList<E> observe(S source) { return observe(Realm.getDefault(), source); } - public IObservableFactory listFactory() { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableList<E>> listFactory() { + return new IObservableFactory<S, IObservableList<E>>() { + public IObservableList<E> createObservable(S target) { return observe(target); } }; } - public IObservableFactory listFactory(final Realm realm) { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableList<E>> listFactory( + final Realm realm) { + return new IObservableFactory<S, IObservableList<E>>() { + public IObservableList<E> createObservable(S target) { return observe(realm, target); } }; } - public IObservableList observeDetail(IObservableValue master) { + public <U extends S> IObservableList<E> observeDetail( + IObservableValue<U> master) { return MasterDetailObservables.detailList(master, listFactory(master.getRealm()), getElementType()); } - public final IListProperty values(IValueProperty detailValue) { - return new ListPropertyDetailValuesList(this, detailValue); + public final <T> IListProperty<S, T> values( + IValueProperty<? super E, T> detailValue) { + return new ListPropertyDetailValuesList<S, E, T>(this, detailValue); } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/MultiListProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/MultiListProperty.java index 2a488d9d..b1069fb4 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/MultiListProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/MultiListProperty.java @@ -27,10 +27,14 @@ import org.eclipse.core.internal.databinding.property.PropertyObservableUtil; * A list property for observing multiple list properties in sequence in a * combined list. * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the list * @since 1.2 */ -public class MultiListProperty extends ListProperty { - private IListProperty[] properties; +public class MultiListProperty<S, E> extends ListProperty<S, E> { + private IListProperty<S, E>[] properties; private Object elementType; /** @@ -40,7 +44,7 @@ public class MultiListProperty extends ListProperty { * @param properties * the list properties */ - public MultiListProperty(IListProperty[] properties) { + public MultiListProperty(IListProperty<S, E>[] properties) { this(properties, null); } @@ -53,7 +57,8 @@ public class MultiListProperty extends ListProperty { * @param elementType * the element type of the MultiListProperty */ - public MultiListProperty(IListProperty[] properties, Object elementType) { + public MultiListProperty(IListProperty<S, E>[] properties, + Object elementType) { this.properties = properties; this.elementType = elementType; } @@ -62,36 +67,36 @@ public class MultiListProperty extends ListProperty { return elementType; } - protected List doGetList(Object source) { - List list = new ArrayList(); + protected List<E> doGetList(S source) { + List<E> list = new ArrayList<E>(); for (int i = 0; i < properties.length; i++) list.addAll(properties[i].getList(source)); return list; } - protected void doUpdateList(final Object source, ListDiff diff) { - diff.accept(new ListDiffVisitor() { - public void handleAdd(int index, Object element) { + protected void doUpdateList(final S source, ListDiff<E> diff) { + diff.accept(new ListDiffVisitor<E>() { + public void handleAdd(int index, E element) { throw new UnsupportedOperationException(); } - public void handleMove(int oldIndex, int newIndex, Object element) { + public void handleMove(int oldIndex, int newIndex, E element) { throw new UnsupportedOperationException(); } - public void handleReplace(int index, Object oldElement, - Object newElement) { + public void handleReplace(int index, E oldElement, E newElement) { int offset = 0; for (int i = 0; i < properties.length; i++) { - List subList = properties[i].getList(source); + List<E> subList = properties[i].getList(source); if (index - offset < subList.size()) { int subListIndex = index - offset; - ListDiffEntry[] entries = new ListDiffEntry[] { - Diffs.createListDiffEntry(subListIndex, false, - oldElement), - Diffs.createListDiffEntry(subListIndex, true, - newElement) }; - ListDiff diff = Diffs.createListDiff(entries); + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>( + 2); + entries.add(Diffs.createListDiffEntry(subListIndex, + false, oldElement)); + entries.add(Diffs.createListDiffEntry(subListIndex, + true, newElement)); + ListDiff<E> diff = Diffs.createListDiff(entries); properties[i].updateList(source, diff); return; } @@ -101,13 +106,13 @@ public class MultiListProperty extends ListProperty { + ", size: " + offset); //$NON-NLS-1$ } - public void handleRemove(int index, Object element) { + public void handleRemove(int index, E element) { int offset = 0; for (int i = 0; i < properties.length; i++) { - List subList = properties[i].getList(source); + List<E> subList = properties[i].getList(source); int subListIndex = index - offset; if (subListIndex < subList.size()) { - ListDiff diff = Diffs.createListDiff(Diffs + ListDiff<E> diff = Diffs.createListDiff(Diffs .createListDiffEntry(subListIndex, false, element)); properties[i].updateList(source, diff); @@ -121,14 +126,17 @@ public class MultiListProperty extends ListProperty { }); } - public IObservableList observe(Realm realm, Object source) { - IObservableList[] lists = new IObservableList[properties.length]; - for (int i = 0; i < lists.length; i++) - lists[i] = properties[i].observe(realm, source); - IObservableList multiList = new MultiList(lists, elementType); + public IObservableList<E> observe(Realm realm, S source) { + List<IObservableList<E>> lists = new ArrayList<IObservableList<E>>( + properties.length); + for (int i = 0; i < properties.length; i++) { + lists.add(properties[i].observe(realm, source)); + } + IObservableList<E> multiList = new MultiList<E>(lists, elementType); - for (int i = 0; i < lists.length; i++) - PropertyObservableUtil.cascadeDispose(multiList, lists[i]); + for (IObservableList<E> list : lists) { + PropertyObservableUtil.cascadeDispose(multiList, list); + } return multiList; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/SimpleListProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/SimpleListProperty.java index 7cbece0f..9e58d617 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/SimpleListProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/list/SimpleListProperty.java @@ -40,16 +40,20 @@ import org.eclipse.core.internal.databinding.property.list.SimplePropertyObserva * In addition, we recommended overriding {@link #toString()} to return a * description suitable for debugging purposes. * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the list * @since 1.2 */ -public abstract class SimpleListProperty extends ListProperty { - public IObservableList observe(Realm realm, Object source) { - return new SimplePropertyObservableList(realm, source, this); +public abstract class SimpleListProperty<S, E> extends ListProperty<S, E> { + public IObservableList<E> observe(Realm realm, S source) { + return new SimplePropertyObservableList<S, E>(realm, source, this); } // Accessors - protected abstract List doGetList(Object source); + protected abstract List<E> doGetList(S source); // Mutators @@ -63,8 +67,9 @@ public abstract class SimpleListProperty extends ListProperty { * @param diff * a diff describing the change * @noreference This method is not intended to be referenced by clients. + * @since 1.5 */ - public final void setList(Object source, List list, ListDiff diff) { + public final void setList(S source, List<E> list, ListDiff<E> diff) { if (source != null && !diff.isEmpty()) { doSetList(source, list, diff); } @@ -81,15 +86,15 @@ public abstract class SimpleListProperty extends ListProperty { * a diff describing the change * @noreference This method is not intended to be referenced by clients. */ - protected abstract void doSetList(Object source, List list, ListDiff diff); + protected abstract void doSetList(S source, List<E> list, ListDiff<E> diff); - protected void doSetList(Object source, List list) { - ListDiff diff = Diffs.computeLazyListDiff(doGetList(source), list); + protected void doSetList(S source, List<E> list) { + ListDiff<E> diff = Diffs.computeLazyListDiff(doGetList(source), list); doSetList(source, list, diff); } - protected void doUpdateList(Object source, ListDiff diff) { - List list = new ArrayList(doGetList(source)); + protected void doUpdateList(S source, ListDiff<E> diff) { + List<E> list = new ArrayList<E>(doGetList(source)); diff.applyTo(list); doSetList(source, list, diff); } @@ -110,6 +115,6 @@ public abstract class SimpleListProperty extends ListProperty { * APIs for this property. * @noreference This method is not intended to be referenced by clients. */ - public abstract INativePropertyListener adaptListener( - ISimplePropertyListener listener); + public abstract INativePropertyListener<S> adaptListener( + ISimplePropertyListener<ListDiff<E>> listener); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java index dc338f67..d2fef6fa 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/DelegatingMapProperty.java @@ -22,13 +22,20 @@ import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; /** + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 * */ -public abstract class DelegatingMapProperty extends MapProperty { +public abstract class DelegatingMapProperty<S, K, V> extends + MapProperty<S, K, V> { private final Object keyType; private final Object valueType; - private final IMapProperty nullProperty = new NullMapProperty(); + private final IMapProperty<S, K, V> nullProperty = new NullMapProperty(); protected DelegatingMapProperty() { this(null, null); @@ -48,10 +55,10 @@ public abstract class DelegatingMapProperty extends MapProperty { * the property source (may be null) * @return the property to delegate to for the specified source object. */ - public final IMapProperty getDelegate(Object source) { + public final IMapProperty<S, K, V> getDelegate(S source) { if (source == null) return nullProperty; - IMapProperty delegate = doGetDelegate(source); + IMapProperty<S, K, V> delegate = doGetDelegate(source); if (delegate == null) delegate = nullProperty; return delegate; @@ -66,7 +73,7 @@ public abstract class DelegatingMapProperty extends MapProperty { * the property source * @return the property to delegate to for the specified source object. */ - protected abstract IMapProperty doGetDelegate(Object source); + protected abstract IMapProperty<S, K, V> doGetDelegate(Object source); public Object getKeyType() { return keyType; @@ -76,42 +83,42 @@ public abstract class DelegatingMapProperty extends MapProperty { return valueType; } - protected Map doGetMap(Object source) { + protected Map<K, V> doGetMap(S source) { return getDelegate(source).getMap(source); } - protected void doSetMap(Object source, Map map) { + protected void doSetMap(S source, Map<K, V> map) { getDelegate(source).setMap(source, map); } - protected void doUpdateMap(Object source, MapDiff diff) { + protected void doUpdateMap(S source, MapDiff<K, V> diff) { getDelegate(source).updateMap(source, diff); } - public IObservableMap observe(Object source) { + public IObservableMap<K, V> observe(S source) { return getDelegate(source).observe(source); } - public IObservableMap observe(Realm realm, Object source) { + public IObservableMap<K, V> observe(Realm realm, S source) { return getDelegate(source).observe(realm, source); } - private class NullMapProperty extends SimpleMapProperty { - protected Map doGetMap(Object source) { - return Collections.EMPTY_MAP; + private class NullMapProperty extends SimpleMapProperty<S, K, V> { + protected Map<K, V> doGetMap(Object source) { + return Collections.emptyMap(); } - protected void doSetMap(Object source, Map map, MapDiff diff) { + protected void doSetMap(S source, Map<K, V> map, MapDiff<K, V> diff) { } - protected void doSetMap(Object source, Map map) { + protected void doSetMap(S source, Map<K, V> map) { } - protected void doUpdateMap(Object source, MapDiff diff) { + protected void doUpdateMap(S source, MapDiff<K, V> diff) { } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<S> adaptListener( + ISimplePropertyListener<MapDiff<K, V>> listener) { return null; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/IMapProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/IMapProperty.java index 018cbace..4ae9d409 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/IMapProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/IMapProperty.java @@ -25,6 +25,12 @@ import org.eclipse.core.databinding.property.value.IValueProperty; /** * Interface for map-typed properties * + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that @@ -34,7 +40,7 @@ import org.eclipse.core.databinding.property.value.IValueProperty; * @see MapProperty * @see SimpleMapProperty */ -public interface IMapProperty extends IProperty { +public interface IMapProperty<S, K, V> extends IProperty { /** * Returns the element type of the map's key set or <code>null</code> if the * key set is untyped. @@ -62,7 +68,7 @@ public interface IMapProperty extends IProperty { * @return a Map with the current contents of the source's map property * @since 1.3 */ - public Map getMap(Object source); + public Map<K, V> getMap(S source); /** * Updates the property on the source with the specified change. @@ -80,7 +86,7 @@ public interface IMapProperty extends IProperty { * the new map * @since 1.3 */ - public void setMap(Object source, Map map); + public void setMap(S source, Map<K, V> map); /** * Updates the property on the source with the specified change. @@ -98,7 +104,7 @@ public interface IMapProperty extends IProperty { * a diff describing the change * @since 1.3 */ - public void updateMap(Object source, MapDiff diff); + public void updateMap(S source, MapDiff<K, V> diff); /** * Returns an observable map observing this map property on the given @@ -109,7 +115,7 @@ public interface IMapProperty extends IProperty { * @return an observable map observing this map-typed property on the given * property source */ - public IObservableMap observe(Object source); + public IObservableMap<K, V> observe(S source); /** * Returns an observable map observing this map property on the given @@ -122,7 +128,7 @@ public interface IMapProperty extends IProperty { * @return an observable map observing this map-typed property on the given * property source */ - public IObservableMap observe(Realm realm, Object source); + public IObservableMap<K, V> observe(Realm realm, S source); /** * Returns a factory for creating observable maps tracking this property of @@ -131,7 +137,7 @@ public interface IMapProperty extends IProperty { * @return a factory for creating observable maps tracking this property of * a particular property source. */ - public IObservableFactory mapFactory(); + public IObservableFactory<S, IObservableMap<K, V>> mapFactory(); /** * Returns a factory for creating observable maps in the given realm, @@ -143,7 +149,7 @@ public interface IMapProperty extends IProperty { * @return a factory for creating observable maps in the given realm, * tracking this property of a particular property source. */ - public IObservableFactory mapFactory(Realm realm); + public IObservableFactory<S, IObservableMap<K, V>> mapFactory(Realm realm); /** * Returns an observable map on the master observable's realm which tracks @@ -155,7 +161,8 @@ public interface IMapProperty extends IProperty { * this property of the values in the entry set of * <code>master</code>. */ - public IObservableMap observeDetail(IObservableValue master); + public <U extends S> IObservableMap<K, V> observeDetail( + IObservableValue<U> master); /** * Returns the nested combination of this property and the specified detail @@ -173,5 +180,6 @@ public interface IMapProperty extends IProperty { * @return the nested combination of the master map and detail value * properties. */ - public IMapProperty values(IValueProperty detailValues); + public <T> IMapProperty<S, K, T> values( + IValueProperty<? super V, T> detailValues); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/MapProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/MapProperty.java index 2b1d5d69..a406a4db 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/MapProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/MapProperty.java @@ -17,7 +17,6 @@ import java.util.Collections; import java.util.Map; import org.eclipse.core.databinding.observable.Diffs; -import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.map.IObservableMap; import org.eclipse.core.databinding.observable.map.MapDiff; @@ -31,9 +30,15 @@ import org.eclipse.core.internal.databinding.property.MapPropertyDetailValuesMap /** * Abstract implementation of IMapProperty * + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 */ -public abstract class MapProperty implements IMapProperty { +public abstract class MapProperty<S, K, V> implements IMapProperty<S, K, V> { /** * By default, this method returns <code>Collections.EMPTY_MAP</code> in @@ -49,9 +54,9 @@ public abstract class MapProperty implements IMapProperty { * * @since 1.3 */ - public Map getMap(Object source) { + public Map<K, V> getMap(S source) { if (source == null) { - return Collections.EMPTY_MAP; + return Collections.emptyMap(); } return Collections.unmodifiableMap(doGetMap(source)); } @@ -62,13 +67,13 @@ public abstract class MapProperty implements IMapProperty { * @param source * the property source * @return a Map with the current contents of the source's map property - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected Map doGetMap(Object source) { - IObservableMap observable = observe(source); + protected Map<K, V> doGetMap(S source) { + IObservableMap<K, V> observable = observe(source); try { - return new IdentityMap(observable); + return new IdentityMap<K, V>(observable); } finally { observable.dispose(); } @@ -77,7 +82,7 @@ public abstract class MapProperty implements IMapProperty { /** * @since 1.3 */ - public final void setMap(Object source, Map map) { + public final void setMap(S source, Map<K, V> map) { if (source != null) { doSetMap(source, map); } @@ -90,18 +95,18 @@ public abstract class MapProperty implements IMapProperty { * the property source * @param map * the new map - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected void doSetMap(Object source, Map map) { - MapDiff diff = Diffs.computeMapDiff(doGetMap(source), map); + protected void doSetMap(S source, Map<K, V> map) { + MapDiff<K, V> diff = Diffs.computeMapDiff(doGetMap(source), map); doUpdateMap(source, diff); } /** * @since 1.3 */ - public final void updateMap(Object source, MapDiff diff) { + public final void updateMap(S source, MapDiff<K, V> diff) { if (source != null) { doUpdateMap(source, diff); } @@ -114,11 +119,11 @@ public abstract class MapProperty implements IMapProperty { * the property source * @param diff * a diff describing the change - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected void doUpdateMap(Object source, MapDiff diff) { - IObservableMap observable = observe(source); + protected void doUpdateMap(S source, MapDiff<K, V> diff) { + IObservableMap<K, V> observable = observe(source); try { diff.applyTo(observable); } finally { @@ -126,32 +131,35 @@ public abstract class MapProperty implements IMapProperty { } } - public IObservableMap observe(Object source) { + public IObservableMap<K, V> observe(S source) { return observe(Realm.getDefault(), source); } - public IObservableFactory mapFactory() { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableMap<K, V>> mapFactory() { + return new IObservableFactory<S, IObservableMap<K, V>>() { + public IObservableMap<K, V> createObservable(S target) { return observe(target); } }; } - public IObservableFactory mapFactory(final Realm realm) { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableMap<K, V>> mapFactory( + final Realm realm) { + return new IObservableFactory<S, IObservableMap<K, V>>() { + public IObservableMap<K, V> createObservable(S target) { return observe(realm, target); } }; } - public IObservableMap observeDetail(IObservableValue master) { + public <U extends S> IObservableMap<K, V> observeDetail( + IObservableValue<U> master) { return MasterDetailObservables.detailMap(master, mapFactory(master.getRealm()), getKeyType(), getValueType()); } - public final IMapProperty values(IValueProperty detailValues) { - return new MapPropertyDetailValuesMap(this, detailValues); + public final <T> IMapProperty<S, K, T> values( + IValueProperty<? super V, T> detailValues) { + return new MapPropertyDetailValuesMap<S, K, V, T>(this, detailValues); } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java index d0ab7995..eb6f6581 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java @@ -41,16 +41,22 @@ import org.eclipse.core.internal.databinding.property.map.SimplePropertyObservab * In addition, we recommended overriding {@link #toString()} to return a * description suitable for debugging purposes. * + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 */ -public abstract class SimpleMapProperty extends MapProperty { - public IObservableMap observe(Realm realm, Object source) { - return new SimplePropertyObservableMap(realm, source, this); +public abstract class SimpleMapProperty<S, K, V> extends MapProperty<S, K, V> { + public IObservableMap<K, V> observe(Realm realm, S source) { + return new SimplePropertyObservableMap<S, K, V>(realm, source, this); } // Accessors - protected abstract Map doGetMap(Object source); + protected abstract Map<K, V> doGetMap(S source); // Mutators @@ -64,8 +70,9 @@ public abstract class SimpleMapProperty extends MapProperty { * @param diff * a diff describing the change * @noreference This method is not intended to be referenced by clients. + * @since 1.5 */ - public final void setMap(Object source, Map map, MapDiff diff) { + public final void setMap(S source, Map<K, V> map, MapDiff<K, V> diff) { if (source != null && !diff.isEmpty()) doSetMap(source, map, diff); } @@ -81,15 +88,15 @@ public abstract class SimpleMapProperty extends MapProperty { * a diff describing the change * @noreference This method is not intended to be referenced by clients. */ - protected abstract void doSetMap(Object source, Map map, MapDiff diff); + protected abstract void doSetMap(S source, Map<K, V> map, MapDiff<K, V> diff); - protected void doSetMap(Object source, Map map) { - MapDiff diff = Diffs.computeLazyMapDiff(doGetMap(source), map); + protected void doSetMap(S source, Map<K, V> map) { + MapDiff<K, V> diff = Diffs.computeLazyMapDiff(doGetMap(source), map); doSetMap(source, map, diff); } - protected void doUpdateMap(Object source, MapDiff diff) { - Map map = new HashMap(doGetMap(source)); + protected void doUpdateMap(S source, MapDiff<K, V> diff) { + Map<K, V> map = new HashMap<K, V>(doGetMap(source)); diff.applyTo(map); doSetMap(source, map, diff); } @@ -111,7 +118,8 @@ public abstract class SimpleMapProperty extends MapProperty { * specified listener, or null if the source object has no listener * APIs for this property. * @noreference This method is not intended to be referenced by clients. + * @since 1.5 */ - public abstract INativePropertyListener adaptListener( - ISimplePropertyListener listener); + public abstract INativePropertyListener<S> adaptListener( + ISimplePropertyListener<MapDiff<K, V>> listener); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java index d65d5bbe..19689ecf 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/DelegatingSetProperty.java @@ -22,12 +22,16 @@ import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; /** + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the set * @since 1.2 * */ -public abstract class DelegatingSetProperty extends SetProperty { +public abstract class DelegatingSetProperty<S, E> extends SetProperty<S, E> { private final Object elementType; - private final ISetProperty nullProperty = new NullSetProperty(); + private final ISetProperty<S, E> nullProperty = new NullSetProperty(); protected DelegatingSetProperty() { this(null); @@ -46,10 +50,10 @@ public abstract class DelegatingSetProperty extends SetProperty { * the property source (may be null) * @return the property to delegate to for the specified source object. */ - protected final ISetProperty getDelegate(Object source) { + protected final ISetProperty<S, E> getDelegate(Object source) { if (source == null) return nullProperty; - ISetProperty delegate = doGetDelegate(source); + ISetProperty<S, E> delegate = doGetDelegate(source); if (delegate == null) delegate = nullProperty; return delegate; @@ -64,52 +68,52 @@ public abstract class DelegatingSetProperty extends SetProperty { * the property source * @return the property to delegate to for the specified source object. */ - protected abstract ISetProperty doGetDelegate(Object source); + protected abstract ISetProperty<S, E> doGetDelegate(Object source); public Object getElementType() { return elementType; } - protected Set doGetSet(Object source) { + protected Set<E> doGetSet(S source) { return getDelegate(source).getSet(source); } - protected void doSetSet(Object source, Set set) { + protected void doSetSet(S source, Set<E> set) { getDelegate(source).setSet(source, set); } - protected void doUpdateSet(Object source, SetDiff diff) { + protected void doUpdateSet(S source, SetDiff<E> diff) { getDelegate(source).updateSet(source, diff); } - public IObservableSet observe(Object source) { + public IObservableSet<E> observe(S source) { return getDelegate(source).observe(source); } - public IObservableSet observe(Realm realm, Object source) { + public IObservableSet<E> observe(Realm realm, S source) { return getDelegate(source).observe(realm, source); } - private class NullSetProperty extends SimpleSetProperty { + private class NullSetProperty extends SimpleSetProperty<S, E> { public Object getElementType() { return elementType; } - protected Set doGetSet(Object source) { - return Collections.EMPTY_SET; + protected Set<E> doGetSet(S source) { + return Collections.emptySet(); } - protected void doSetSet(Object source, Set set, SetDiff diff) { + protected void doSetSet(S source, Set<E> set, SetDiff<E> diff) { } - protected void doSetSet(Object source, Set set) { + protected void doSetSet(S source, Set<E> set) { } - protected void doUpdateSet(Object source, SetDiff diff) { + protected void doUpdateSet(S source, SetDiff<E> diff) { } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<S> adaptListener( + ISimplePropertyListener<SetDiff<E>> listener) { return null; } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/ISetProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/ISetProperty.java index fc593f2f..40a8b636 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/ISetProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/ISetProperty.java @@ -27,6 +27,10 @@ import org.eclipse.core.databinding.property.value.IValueProperty; /** * Interface for set-typed properties * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the set * @since 1.2 * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that @@ -36,7 +40,7 @@ import org.eclipse.core.databinding.property.value.IValueProperty; * @see SetProperty * @see SimpleSetProperty */ -public interface ISetProperty extends IProperty { +public interface ISetProperty<S, E> extends IProperty { /** * Returns the type of the elements in the collection or <code>null</code> * if untyped @@ -56,7 +60,7 @@ public interface ISetProperty extends IProperty { * property * @since 1.3 */ - public Set getSet(Object source); + public Set<E> getSet(S source); /** * Updates the property on the source with the specified change. @@ -74,7 +78,7 @@ public interface ISetProperty extends IProperty { * the new set * @since 1.3 */ - public void setSet(Object source, Set set); + public void setSet(S source, Set<E> set); /** * Updates the property on the source with the specified change. @@ -92,7 +96,7 @@ public interface ISetProperty extends IProperty { * a diff describing the change * @since 1.3 */ - public void updateSet(Object source, SetDiff diff); + public void updateSet(S source, SetDiff<E> diff); /** * Returns an observable set observing this set property on the given @@ -103,7 +107,7 @@ public interface ISetProperty extends IProperty { * @return an observable set observing this set property on the given * property source */ - public IObservableSet observe(Object source); + public IObservableSet<E> observe(S source); /** * Returns an observable set observing this set property on the given @@ -116,7 +120,7 @@ public interface ISetProperty extends IProperty { * @return an observable set observing this set property on the given * property source */ - public IObservableSet observe(Realm realm, Object source); + public IObservableSet<E> observe(Realm realm, S source); /** * Returns a factory for creating observable sets tracking this property of @@ -125,7 +129,7 @@ public interface ISetProperty extends IProperty { * @return a factory for creating observable sets tracking this property of * a particular property source. */ - public IObservableFactory setFactory(); + public IObservableFactory<S, IObservableSet<E>> setFactory(); /** * Returns a factory for creating observable sets in the given realm, @@ -137,7 +141,7 @@ public interface ISetProperty extends IProperty { * @return a factory for creating observable sets in the given realm, * tracking this property of a particular property source. */ - public IObservableFactory setFactory(Realm realm); + public IObservableFactory<S, IObservableSet<E>> setFactory(Realm realm); /** * Returns an observable set on the master observable's realm which tracks @@ -148,7 +152,8 @@ public interface ISetProperty extends IProperty { * @return an observable set on the given realm which tracks this property * of the current value of <code>master</code>. */ - public IObservableSet observeDetail(IObservableValue master); + public <U extends S> IObservableSet<E> observeDetail( + IObservableValue<U> master); /** * Returns the nested combination of this property and the specified detail @@ -166,5 +171,6 @@ public interface ISetProperty extends IProperty { * @return the nested combination of the master set and detail value * properties */ - public IMapProperty values(IValueProperty detailValues); + public <T> IMapProperty<S, E, T> values( + IValueProperty<? super E, T> detailValues); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SetProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SetProperty.java index 52c68c82..b52a40e4 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SetProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SetProperty.java @@ -17,7 +17,6 @@ import java.util.Collections; import java.util.Set; import org.eclipse.core.databinding.observable.Diffs; -import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory; import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables; @@ -32,9 +31,13 @@ import org.eclipse.core.internal.databinding.property.SetPropertyDetailValuesMap /** * Abstract implementation of ISetProperty * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the set * @since 1.2 */ -public abstract class SetProperty implements ISetProperty { +public abstract class SetProperty<S, E> implements ISetProperty<S, E> { /** * By default, this method returns <code>Collections.EMPTY_SET</code> in @@ -50,9 +53,9 @@ public abstract class SetProperty implements ISetProperty { * * @since 1.3 */ - public Set getSet(Object source) { + public final Set<E> getSet(S source) { if (source == null) { - return Collections.EMPTY_SET; + return Collections.emptySet(); } return Collections.unmodifiableSet(doGetSet(source)); } @@ -63,13 +66,13 @@ public abstract class SetProperty implements ISetProperty { * @param source * the property source * @return a Set with the current contents of the source's set property - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected Set doGetSet(Object source) { - IObservableSet observable = observe(source); + protected Set<E> doGetSet(S source) { + IObservableSet<E> observable = observe(source); try { - return new IdentitySet(observable); + return new IdentitySet<E>(observable); } finally { observable.dispose(); } @@ -78,7 +81,7 @@ public abstract class SetProperty implements ISetProperty { /** * @since 1.3 */ - public final void setSet(Object source, Set set) { + public final void setSet(S source, Set<E> set) { if (source != null) { doSetSet(source, set); } @@ -91,17 +94,17 @@ public abstract class SetProperty implements ISetProperty { * the property source * @param set * the new set - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected void doSetSet(Object source, Set set) { + protected void doSetSet(S source, Set<E> set) { doUpdateSet(source, Diffs.computeSetDiff(doGetSet(source), set)); } /** * @since 1.3 */ - public final void updateSet(Object source, SetDiff diff) { + public final void updateSet(S source, SetDiff<E> diff) { if (source != null && !diff.isEmpty()) { doUpdateSet(source, diff); } @@ -114,11 +117,11 @@ public abstract class SetProperty implements ISetProperty { * the property source * @param diff * a diff describing the change - * @since 1.3 + * @since 1.5 * @noreference This method is not intended to be referenced by clients. */ - protected void doUpdateSet(Object source, SetDiff diff) { - IObservableSet observable = observe(source); + protected void doUpdateSet(S source, SetDiff<E> diff) { + IObservableSet<E> observable = observe(source); try { diff.applyTo(observable); } finally { @@ -126,32 +129,34 @@ public abstract class SetProperty implements ISetProperty { } } - public IObservableSet observe(Object source) { + public IObservableSet<E> observe(S source) { return observe(Realm.getDefault(), source); } - public IObservableFactory setFactory() { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableSet<E>> setFactory() { + return new IObservableFactory<S, IObservableSet<E>>() { + public IObservableSet<E> createObservable(S target) { return observe(target); } }; } - public IObservableFactory setFactory(final Realm realm) { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableSet<E>> setFactory(final Realm realm) { + return new IObservableFactory<S, IObservableSet<E>>() { + public IObservableSet<E> createObservable(S target) { return observe(realm, target); } }; } - public IObservableSet observeDetail(IObservableValue master) { + public <U extends S> IObservableSet<E> observeDetail( + IObservableValue<U> master) { return MasterDetailObservables.detailSet(master, setFactory(master.getRealm()), getElementType()); } - public final IMapProperty values(IValueProperty detailValues) { - return new SetPropertyDetailValuesMap(this, detailValues); + public final <T> IMapProperty<S, E, T> values( + IValueProperty<? super E, T> detailValues) { + return new SetPropertyDetailValuesMap<S, E, T>(this, detailValues); } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java index 85273c7a..85ae508c 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java @@ -40,16 +40,20 @@ import org.eclipse.core.internal.databinding.property.set.SimplePropertyObservab * In addition, we recommended overriding {@link #toString()} to return a * description suitable for debugging purposes. * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the set * @since 1.2 */ -public abstract class SimpleSetProperty extends SetProperty { - public IObservableSet observe(Realm realm, Object source) { - return new SimplePropertyObservableSet(realm, source, this); +public abstract class SimpleSetProperty<S, E> extends SetProperty<S, E> { + public IObservableSet<E> observe(Realm realm, S source) { + return new SimplePropertyObservableSet<S, E>(realm, source, this); } // Accessors - protected abstract Set doGetSet(Object source); + protected abstract Set<E> doGetSet(S source); // Mutators @@ -64,7 +68,7 @@ public abstract class SimpleSetProperty extends SetProperty { * a diff describing the change * @noreference This method is not intended to be referenced by clients. */ - public final void setSet(Object source, Set set, SetDiff diff) { + public final void setSet(S source, Set<E> set, SetDiff<E> diff) { if (source != null && !diff.isEmpty()) doSetSet(source, set, diff); } @@ -80,15 +84,15 @@ public abstract class SimpleSetProperty extends SetProperty { * a diff describing the change * @noreference This method is not intended to be referenced by clients. */ - protected abstract void doSetSet(Object source, Set set, SetDiff diff); + protected abstract void doSetSet(S source, Set<E> set, SetDiff<E> diff); - protected void doSetSet(Object source, Set set) { - SetDiff diff = Diffs.computeLazySetDiff(doGetSet(source), set); + protected void doSetSet(S source, Set<E> set) { + SetDiff<E> diff = Diffs.computeLazySetDiff(doGetSet(source), set); doSetSet(source, set, diff); } - protected void doUpdateSet(Object source, SetDiff diff) { - Set set = new HashSet(doGetSet(source)); + protected void doUpdateSet(S source, SetDiff<E> diff) { + Set<E> set = new HashSet<E>(doGetSet(source)); diff.applyTo(set); doSetSet(source, set, diff); } @@ -111,6 +115,6 @@ public abstract class SimpleSetProperty extends SetProperty { * APIs for this property. * @noreference This method is not intended to be referenced by clients. */ - public abstract INativePropertyListener adaptListener( - ISimplePropertyListener listener); + public abstract INativePropertyListener<S> adaptListener( + ISimplePropertyListener<SetDiff<E>> listener); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/UnionSetProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/UnionSetProperty.java index 3c384ccc..7b7a081b 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/UnionSetProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/set/UnionSetProperty.java @@ -24,16 +24,20 @@ import org.eclipse.core.internal.databinding.property.PropertyObservableUtil; * A set property for observing the union of multiple set properties a combined * set. * + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the set * @since 1.2 */ -public class UnionSetProperty extends SetProperty { - private final ISetProperty[] properties; +public class UnionSetProperty<S, E> extends SetProperty<S, E> { + private final ISetProperty<S, E>[] properties; private final Object elementType; /** * @param properties */ - public UnionSetProperty(ISetProperty[] properties) { + public UnionSetProperty(ISetProperty<S, E>[] properties) { this(properties, null); } @@ -41,7 +45,7 @@ public class UnionSetProperty extends SetProperty { * @param properties * @param elementType */ - public UnionSetProperty(ISetProperty[] properties, Object elementType) { + public UnionSetProperty(ISetProperty<S, E>[] properties, Object elementType) { this.properties = properties; this.elementType = elementType; } @@ -50,31 +54,34 @@ public class UnionSetProperty extends SetProperty { return elementType; } - protected Set doGetSet(Object source) { - Set set = new HashSet(); + protected Set<E> doGetSet(S source) { + Set<E> set = new HashSet<E>(); for (int i = 0; i < properties.length; i++) set.addAll(properties[i].getSet(source)); return set; } - protected void doSetSet(Object source, Set set) { + protected void doSetSet(S source, Set<E> set) { throw new UnsupportedOperationException( "UnionSetProperty is unmodifiable"); //$NON-NLS-1$ } - protected void doUpdateSet(Object source, SetDiff diff) { + protected void doUpdateSet(S source, SetDiff<E> diff) { throw new UnsupportedOperationException( "UnionSetProperty is unmodifiable"); //$NON-NLS-1$ } - public IObservableSet observe(Realm realm, Object source) { - IObservableSet[] sets = new IObservableSet[properties.length]; - for (int i = 0; i < sets.length; i++) - sets[i] = properties[i].observe(realm, source); - IObservableSet unionSet = new UnionSet(sets, elementType); + public IObservableSet<E> observe(Realm realm, S source) { + Set<IObservableSet<? extends E>> sets = new HashSet<IObservableSet<? extends E>>( + properties.length); + for (ISetProperty<S, E> property : properties) { + sets.add(property.observe(realm, source)); + } + IObservableSet<E> unionSet = new UnionSet<E>(sets, elementType); - for (int i = 0; i < sets.length; i++) - PropertyObservableUtil.cascadeDispose(unionSet, sets[i]); + for (IObservableSet<? extends E> set : sets) { + PropertyObservableUtil.cascadeDispose(unionSet, set); + } return unionSet; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java index 3dac917a..1b6d6161 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/DelegatingValueProperty.java @@ -17,6 +17,7 @@ import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.map.IObservableMap; import org.eclipse.core.databinding.observable.set.IObservableSet; import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.internal.databinding.property.value.ListDelegatingValueObservableList; @@ -24,12 +25,16 @@ import org.eclipse.core.internal.databinding.property.value.MapDelegatingValueOb import org.eclipse.core.internal.databinding.property.value.SetDelegatingValueObservableMap; /** + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property * @since 1.2 * */ -public abstract class DelegatingValueProperty extends ValueProperty { +public abstract class DelegatingValueProperty<S, T> extends ValueProperty<S, T> { private final Object valueType; - private final IValueProperty nullProperty = new NullValueProperty(); + private final IValueProperty<S, T> nullProperty = new NullValueProperty(); protected DelegatingValueProperty() { this(null); @@ -48,10 +53,10 @@ public abstract class DelegatingValueProperty extends ValueProperty { * the property source (may be null) * @return the property to delegate to for the specified source object. */ - public final IValueProperty getDelegate(Object source) { + public final IValueProperty<S, T> getDelegate(S source) { if (source == null) return nullProperty; - IValueProperty delegate = doGetDelegate(source); + IValueProperty<S, T> delegate = doGetDelegate(source); if (delegate == null) delegate = nullProperty; return delegate; @@ -66,13 +71,13 @@ public abstract class DelegatingValueProperty extends ValueProperty { * the property source * @return the property to delegate to for the specified source object. */ - protected abstract IValueProperty doGetDelegate(Object source); + protected abstract IValueProperty<S, T> doGetDelegate(S source); - protected Object doGetValue(Object source) { + protected T doGetValue(S source) { return getDelegate(source).getValue(source); } - protected void doSetValue(Object source, Object value) { + protected void doSetValue(S source, T value) { getDelegate(source).setValue(source, value); } @@ -80,40 +85,43 @@ public abstract class DelegatingValueProperty extends ValueProperty { return valueType; } - public IObservableValue observe(Object source) { + public IObservableValue<T> observe(S source) { return getDelegate(source).observe(source); } - public IObservableValue observe(Realm realm, Object source) { + public IObservableValue<T> observe(Realm realm, S source) { return getDelegate(source).observe(realm, source); } - public IObservableList observeDetail(IObservableList master) { - return new ListDelegatingValueObservableList(master, this); + public <U extends S> IObservableList<T> observeDetail( + IObservableList<U> master) { + return new ListDelegatingValueObservableList<S, U, T>(master, this); } - public IObservableMap observeDetail(IObservableSet master) { - return new SetDelegatingValueObservableMap(master, this); + public <U extends S> IObservableMap<U, T> observeDetail( + IObservableSet<U> master) { + return new SetDelegatingValueObservableMap<S, U, T>(master, this); } - public IObservableMap observeDetail(IObservableMap master) { - return new MapDelegatingValueObservableMap(master, this); + public <K, V extends S> IObservableMap<K, T> observeDetail( + IObservableMap<K, V> master) { + return new MapDelegatingValueObservableMap<S, K, V, T>(master, this); } - private class NullValueProperty extends SimpleValueProperty { + private class NullValueProperty extends SimpleValueProperty<S, T> { public Object getValueType() { return valueType; } - protected Object doGetValue(Object source) { + protected T doGetValue(S source) { return null; } - protected void doSetValue(Object source, Object value) { + protected void doSetValue(S source, T value) { } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<S> adaptListener( + ISimplePropertyListener<ValueDiff<T>> listener) { return null; } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/IValueProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/IValueProperty.java index 162ccb72..f811ea17 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/IValueProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/IValueProperty.java @@ -26,6 +26,11 @@ import org.eclipse.core.databinding.property.set.ISetProperty; /** * Interface for value-typed properties * + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property + * * @since 1.2 * @noimplement This interface is not intended to be implemented by clients. * Clients should instead subclass one of the classes that @@ -35,7 +40,7 @@ import org.eclipse.core.databinding.property.set.ISetProperty; * @see ValueProperty * @see SimpleValueProperty */ -public interface IValueProperty extends IProperty { +public interface IValueProperty<S, T> extends IProperty { /** * Returns the value type of the property, or <code>null</code> if untyped. * @@ -53,7 +58,7 @@ public interface IValueProperty extends IProperty { * source. * @since 1.3 */ - public Object getValue(Object source); + public T getValue(S source); /** * Sets this property on the specified property source to the specified @@ -71,7 +76,7 @@ public interface IValueProperty extends IProperty { * the new property value * @since 1.3 */ - public void setValue(Object source, Object value); + public void setValue(S source, T value); /** * Returns an observable value observing this value property on the given @@ -82,7 +87,7 @@ public interface IValueProperty extends IProperty { * @return an observable value observing this value property on the given * property source */ - public IObservableValue observe(Object source); + public IObservableValue<T> observe(S source); /** * Returns an observable value observing this value property on the given @@ -95,7 +100,7 @@ public interface IValueProperty extends IProperty { * @return an observable value observing this value property on the given * property source */ - public IObservableValue observe(Realm realm, Object source); + public IObservableValue<T> observe(Realm realm, S source); /** * Returns a factory for creating observable values tracking this property @@ -104,7 +109,7 @@ public interface IValueProperty extends IProperty { * @return a factory for creating observable values tracking this property * of a particular property source. */ - public IObservableFactory valueFactory(); + public IObservableFactory<S, IObservableValue<T>> valueFactory(); /** * Returns a factory for creating observable values in the given realm, @@ -116,7 +121,7 @@ public interface IValueProperty extends IProperty { * @return a factory for creating observable values in the given realm, * tracking this property of a particular property source. */ - public IObservableFactory valueFactory(Realm realm); + public IObservableFactory<S, IObservableValue<T>> valueFactory(Realm realm); /** * Returns an observable value on the master observable's realm which tracks @@ -127,7 +132,8 @@ public interface IValueProperty extends IProperty { * @return an observable value which tracks this property of the current * value of <code>master</code>. */ - public IObservableValue observeDetail(IObservableValue master); + public <M extends S> IObservableValue<T> observeDetail( + IObservableValue<M> master); /** * Returns an observable list on the master observable's realm which tracks @@ -138,7 +144,8 @@ public interface IValueProperty extends IProperty { * @return an observable list which tracks this property on each element of * the master observable. */ - public IObservableList observeDetail(IObservableList master); + public <M extends S> IObservableList<T> observeDetail( + IObservableList<M> master); /** * Returns an observable map on the master observable's realm where the @@ -150,7 +157,8 @@ public interface IValueProperty extends IProperty { * @return an observable map that tracks the current value of this property * for the elements in the given set. */ - public IObservableMap observeDetail(IObservableSet master); + public <M extends S> IObservableMap<M, T> observeDetail( + IObservableSet<M> master); /** * Returns an observable map on the master observable's realm where the @@ -164,7 +172,8 @@ public interface IValueProperty extends IProperty { * the current value of this property for the elements in the given * map's values collection */ - public IObservableMap observeDetail(IObservableMap master); + public <K, V extends S> IObservableMap<K, T> observeDetail( + IObservableMap<K, V> master); /** * Returns the nested combination of this property and the specified detail @@ -176,7 +185,8 @@ public interface IValueProperty extends IProperty { * the detail property * @return the nested combination of the master and detail properties */ - public IValueProperty value(IValueProperty detailValue); + public <M> IValueProperty<S, M> value( + IValueProperty<? super T, M> detailValue); /** * Returns the nested combination of this property and the specified detail @@ -189,7 +199,7 @@ public interface IValueProperty extends IProperty { * @return the nested combination of the master value and detail list * properties */ - public IListProperty list(IListProperty detailList); + public <E> IListProperty<S, E> list(IListProperty<? super T, E> detailList); /** * Returns the nested combination of this property and the specified detail @@ -202,7 +212,7 @@ public interface IValueProperty extends IProperty { * @return the nested combination of the master value and detail set * properties */ - public ISetProperty set(ISetProperty detailSet); + public <E> ISetProperty<S, E> set(ISetProperty<? super T, E> detailSet); /** * Returns the nested combination of this property and the specified detail @@ -215,5 +225,6 @@ public interface IValueProperty extends IProperty { * @return the nested combination of the master value and detial map * properties */ - public IMapProperty map(IMapProperty detailMap); + public <K, V> IMapProperty<S, K, V> map( + IMapProperty<? super T, K, V> detailMap); } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java index 9293c85e..dc195262 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java @@ -17,6 +17,7 @@ import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.map.IObservableMap; import org.eclipse.core.databinding.observable.set.IObservableSet; import org.eclipse.core.databinding.observable.value.IObservableValue; +import org.eclipse.core.databinding.observable.value.ValueDiff; import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.internal.databinding.property.value.ListSimpleValueObservableList; @@ -40,12 +41,16 @@ import org.eclipse.core.internal.databinding.property.value.SimplePropertyObserv * In addition, we recommended overriding {@link #toString()} to return a * description suitable for debugging purposes. * + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property * @since 1.2 */ -public abstract class SimpleValueProperty extends ValueProperty { - protected abstract Object doGetValue(Object source); +public abstract class SimpleValueProperty<S, T> extends ValueProperty<S, T> { + protected abstract T doGetValue(S source); - protected abstract void doSetValue(Object source, Object value); + protected abstract void doSetValue(S source, T value); /** * Returns a listener capable of adding or removing itself as a listener on @@ -63,22 +68,25 @@ public abstract class SimpleValueProperty extends ValueProperty { * APIs for this property. * @noreference This method is not intended to be referenced by clients. */ - public abstract INativePropertyListener adaptListener( - ISimplePropertyListener listener); + public abstract INativePropertyListener<S> adaptListener( + ISimplePropertyListener<ValueDiff<T>> listener); - public IObservableValue observe(Realm realm, Object source) { - return new SimplePropertyObservableValue(realm, source, this); + public IObservableValue<T> observe(Realm realm, S source) { + return new SimplePropertyObservableValue<S, T>(realm, source, this); } - public IObservableList observeDetail(IObservableList master) { - return new ListSimpleValueObservableList(master, this); + public <U extends S> IObservableList<T> observeDetail( + IObservableList<U> master) { + return new ListSimpleValueObservableList<S, U, T>(master, this); } - public IObservableMap observeDetail(IObservableSet master) { - return new SetSimpleValueObservableMap(master, this); + public <U extends S> IObservableMap<U, T> observeDetail( + IObservableSet<U> master) { + return new SetSimpleValueObservableMap<S, U, T>(master, this); } - public IObservableMap observeDetail(IObservableMap master) { - return new MapSimpleValueObservableMap(master, this); + public <K, V extends S> IObservableMap<K, T> observeDetail( + IObservableMap<K, V> master) { + return new MapSimpleValueObservableMap<S, K, V, T>(master, this); } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/ValueProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/ValueProperty.java index 5024b3bd..9ff72206 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/ValueProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/databinding/property/value/ValueProperty.java @@ -13,7 +13,6 @@ package org.eclipse.core.databinding.property.value; -import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.map.IObservableMap; @@ -32,9 +31,13 @@ import org.eclipse.core.internal.databinding.property.ValuePropertyDetailValue; /** * Abstract implementation of IValueProperty * + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property * @since 1.2 */ -public abstract class ValueProperty implements IValueProperty { +public abstract class ValueProperty<S, T> implements IValueProperty<S, T> { /** * By default, this method returns <code>null</code> in case the source @@ -50,7 +53,7 @@ public abstract class ValueProperty implements IValueProperty { * * @since 1.3 */ - public Object getValue(Object source) { + public T getValue(S source) { if (source == null) { return null; } @@ -66,8 +69,8 @@ public abstract class ValueProperty implements IValueProperty { * @noreference This method is not intended to be referenced by clients. * @since 1.3 */ - protected Object doGetValue(Object source) { - IObservableValue observable = observe(source); + protected T doGetValue(S source) { + IObservableValue<T> observable = observe(source); try { return observable.getValue(); } finally { @@ -78,7 +81,7 @@ public abstract class ValueProperty implements IValueProperty { /** * @since 1.3 */ - public final void setValue(Object source, Object value) { + public final void setValue(S source, T value) { if (source != null) { doSetValue(source, value); } @@ -94,8 +97,8 @@ public abstract class ValueProperty implements IValueProperty { * @since 1.3 * @noreference This method is not intended to be referenced by clients. */ - protected void doSetValue(Object source, Object value) { - IObservableValue observable = observe(source); + protected void doSetValue(S source, T value) { + IObservableValue<T> observable = observe(source); try { observable.setValue(value); } finally { @@ -103,27 +106,29 @@ public abstract class ValueProperty implements IValueProperty { } } - public IObservableValue observe(Object source) { + public IObservableValue<T> observe(S source) { return observe(Realm.getDefault(), source); } - public IObservableFactory valueFactory() { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableValue<T>> valueFactory() { + return new IObservableFactory<S, IObservableValue<T>>() { + public IObservableValue<T> createObservable(S target) { return observe(target); } }; } - public IObservableFactory valueFactory(final Realm realm) { - return new IObservableFactory() { - public IObservable createObservable(Object target) { + public IObservableFactory<S, IObservableValue<T>> valueFactory( + final Realm realm) { + return new IObservableFactory<S, IObservableValue<T>>() { + public IObservableValue<T> createObservable(S target) { return observe(realm, target); } }; } - public IObservableValue observeDetail(IObservableValue master) { + public <U extends S> IObservableValue<T> observeDetail( + IObservableValue<U> master) { return MasterDetailObservables.detailValue(master, valueFactory(master.getRealm()), getValueType()); } @@ -131,7 +136,8 @@ public abstract class ValueProperty implements IValueProperty { /** * @since 1.4 */ - public IObservableList observeDetail(IObservableList master) { + public <V extends S> IObservableList<T> observeDetail( + IObservableList<V> master) { return MasterDetailObservables.detailValues(master, valueFactory(master.getRealm()), getValueType()); } @@ -139,7 +145,8 @@ public abstract class ValueProperty implements IValueProperty { /** * @since 1.4 */ - public IObservableMap observeDetail(IObservableSet master) { + public <V extends S> IObservableMap<V, T> observeDetail( + IObservableSet<V> master) { return MasterDetailObservables.detailValues(master, valueFactory(master.getRealm()), getValueType()); } @@ -147,24 +154,28 @@ public abstract class ValueProperty implements IValueProperty { /** * @since 1.4 */ - public IObservableMap observeDetail(IObservableMap master) { + public <K, V extends S> IObservableMap<K, T> observeDetail( + IObservableMap<K, V> master) { return MasterDetailObservables.detailValues(master, valueFactory(master.getRealm()), getValueType()); } - public final IValueProperty value(IValueProperty detailValue) { - return new ValuePropertyDetailValue(this, detailValue); + public final <U> IValueProperty<S, U> value( + IValueProperty<? super T, U> detailValue) { + return new ValuePropertyDetailValue<S, T, U>(this, detailValue); } - public final IListProperty list(IListProperty detailList) { - return new ValuePropertyDetailList(this, detailList); + public final <E> IListProperty<S, E> list( + IListProperty<? super T, E> detailList) { + return new ValuePropertyDetailList<S, T, E>(this, detailList); } - public final ISetProperty set(ISetProperty detailSet) { - return new ValuePropertyDetailSet(this, detailSet); + public final <E> ISetProperty<S, E> set(ISetProperty<? super T, E> detailSet) { + return new ValuePropertyDetailSet<S, T, E>(this, detailSet); } - public final IMapProperty map(IMapProperty detailMap) { - return new ValuePropertyDetailMap(this, detailMap); + public final <K, V> IMapProperty<S, K, V> map( + IMapProperty<? super T, K, V> detailMap) { + return new ValuePropertyDetailMap<S, T, K, V>(this, detailMap); } } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ListPropertyDetailValuesList.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ListPropertyDetailValuesList.java index 15928f35..d864bfe9 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ListPropertyDetailValuesList.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ListPropertyDetailValuesList.java @@ -27,19 +27,25 @@ import org.eclipse.core.databinding.property.list.ListProperty; import org.eclipse.core.databinding.property.value.IValueProperty; /** + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property + * @param <E> + * type of the elements in the list * @since 3.3 * */ -public class ListPropertyDetailValuesList extends ListProperty { - private final IListProperty masterProperty; - private final IValueProperty detailProperty; +public class ListPropertyDetailValuesList<S, T, E> extends ListProperty<S, E> { + private final IListProperty<S, T> masterProperty; + private final IValueProperty<? super T, E> detailProperty; /** * @param masterProperty * @param detailProperty */ - public ListPropertyDetailValuesList(IListProperty masterProperty, - IValueProperty detailProperty) { + public ListPropertyDetailValuesList(IListProperty<S, T> masterProperty, + IValueProperty<? super T, E> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -48,38 +54,37 @@ public class ListPropertyDetailValuesList extends ListProperty { return detailProperty.getValueType(); } - protected List doGetList(Object source) { - List masterList = masterProperty.getList(source); - List detailList = new ArrayList(masterList.size()); - for (Iterator it = masterList.iterator(); it.hasNext();) + protected List<E> doGetList(S source) { + List<T> masterList = masterProperty.getList(source); + List<E> detailList = new ArrayList<E>(masterList.size()); + for (Iterator<T> it = masterList.iterator(); it.hasNext();) detailList.add(detailProperty.getValue(it.next())); return detailList; } - protected void doUpdateList(Object source, ListDiff diff) { - final List masterList = masterProperty.getList(source); - diff.accept(new ListDiffVisitor() { - public void handleAdd(int index, Object element) { + protected void doUpdateList(S source, ListDiff<E> diff) { + final List<T> masterList = masterProperty.getList(source); + diff.accept(new ListDiffVisitor<E>() { + public void handleAdd(int index, E element) { throw new UnsupportedOperationException(); } - public void handleRemove(int index, Object element) { + public void handleRemove(int index, E element) { throw new UnsupportedOperationException(); } - public void handleMove(int oldIndex, int newIndex, Object element) { + public void handleMove(int oldIndex, int newIndex, E element) { throw new UnsupportedOperationException(); } - public void handleReplace(int index, Object oldElement, - Object newElement) { + public void handleReplace(int index, E oldElement, E newElement) { detailProperty.setValue(masterList.get(index), newElement); } }); } - public IObservableList observe(Realm realm, Object source) { - IObservableList masterList; + public IObservableList<E> observe(Realm realm, S source) { + IObservableList<T> masterList; ObservableTracker.setIgnore(true); try { @@ -88,13 +93,15 @@ public class ListPropertyDetailValuesList extends ListProperty { ObservableTracker.setIgnore(false); } - IObservableList detailList = detailProperty.observeDetail(masterList); + IObservableList<E> detailList = detailProperty + .observeDetail(masterList); PropertyObservableUtil.cascadeDispose(detailList, masterList); return detailList; } - public IObservableList observeDetail(IObservableValue master) { - IObservableList masterList; + public <U extends S> IObservableList<E> observeDetail( + IObservableValue<U> master) { + IObservableList<T> masterList; ObservableTracker.setIgnore(true); try { @@ -103,7 +110,8 @@ public class ListPropertyDetailValuesList extends ListProperty { ObservableTracker.setIgnore(false); } - IObservableList detailList = detailProperty.observeDetail(masterList); + IObservableList<E> detailList = detailProperty + .observeDetail(masterList); PropertyObservableUtil.cascadeDispose(detailList, masterList); return detailList; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/MapPropertyDetailValuesMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/MapPropertyDetailValuesMap.java index 1d699855..69e1a297 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/MapPropertyDetailValuesMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/MapPropertyDetailValuesMap.java @@ -26,19 +26,29 @@ import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.core.internal.databinding.identity.IdentityMap; /** + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map + * @param <T> + * type of the elements in the list, being the type of the value of + * the detail property * @since 3.3 * */ -public class MapPropertyDetailValuesMap extends MapProperty { - private final IMapProperty masterProperty; - private final IValueProperty detailProperty; +public class MapPropertyDetailValuesMap<S, K, V, T> extends + MapProperty<S, K, T> { + private final IMapProperty<S, K, V> masterProperty; + private final IValueProperty<? super V, T> detailProperty; /** * @param masterProperty * @param detailProperty */ - public MapPropertyDetailValuesMap(IMapProperty masterProperty, - IValueProperty detailProperty) { + public MapPropertyDetailValuesMap(IMapProperty<S, K, V> masterProperty, + IValueProperty<? super V, T> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -51,34 +61,33 @@ public class MapPropertyDetailValuesMap extends MapProperty { return detailProperty.getValueType(); } - protected Map doGetMap(Object source) { - Map masterMap = masterProperty.getMap(source); - Map detailMap = new IdentityMap(); - for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - detailMap.put(entry.getKey(), detailProperty.getValue(entry - .getValue())); + protected Map<K, T> doGetMap(S source) { + Map<K, V> masterMap = masterProperty.getMap(source); + Map<K, T> detailMap = new IdentityMap<K, T>(); + for (Map.Entry<K, V> entry : masterMap.entrySet()) { + detailMap.put(entry.getKey(), + detailProperty.getValue(entry.getValue())); } return detailMap; } - protected void doUpdateMap(Object source, MapDiff diff) { + protected void doUpdateMap(S source, MapDiff<K, T> diff) { if (!diff.getAddedKeys().isEmpty()) throw new UnsupportedOperationException(toString() + " does not support entry additions"); //$NON-NLS-1$ if (!diff.getRemovedKeys().isEmpty()) throw new UnsupportedOperationException(toString() + " does not support entry removals"); //$NON-NLS-1$ - Map masterMap = masterProperty.getMap(source); - for (Iterator it = diff.getChangedKeys().iterator(); it.hasNext();) { - Object key = it.next(); - Object masterValue = masterMap.get(key); + Map<K, V> masterMap = masterProperty.getMap(source); + for (Iterator<K> it = diff.getChangedKeys().iterator(); it.hasNext();) { + K key = it.next(); + V masterValue = masterMap.get(key); detailProperty.setValue(masterValue, diff.getNewValue(key)); } } - public IObservableMap observe(Realm realm, Object source) { - IObservableMap masterMap; + public IObservableMap<K, T> observe(Realm realm, S source) { + IObservableMap<K, V> masterMap; ObservableTracker.setIgnore(true); try { @@ -87,13 +96,15 @@ public class MapPropertyDetailValuesMap extends MapProperty { ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterMap); + IObservableMap<K, T> detailMap = detailProperty + .observeDetail(masterMap); PropertyObservableUtil.cascadeDispose(detailMap, masterMap); return detailMap; } - public IObservableMap observeDetail(IObservableValue master) { - IObservableMap masterMap; + public <U extends S> IObservableMap<K, T> observeDetail( + IObservableValue<U> master) { + IObservableMap<K, V> masterMap; ObservableTracker.setIgnore(true); try { @@ -102,7 +113,8 @@ public class MapPropertyDetailValuesMap extends MapProperty { ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterMap); + IObservableMap<K, T> detailMap = detailProperty + .observeDetail(masterMap); PropertyObservableUtil.cascadeDispose(detailMap, masterMap); return detailMap; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/SetPropertyDetailValuesMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/SetPropertyDetailValuesMap.java index 98308c47..4b336c69 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/SetPropertyDetailValuesMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/SetPropertyDetailValuesMap.java @@ -28,19 +28,26 @@ import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.core.internal.databinding.identity.IdentityMap; /** + * @param <S> + * type of the source object + * @param <M> + * type of the elements in the master set + * @param <T> + * type of the elements in the list, being the type of the value of + * the detail property * @since 3.3 * */ -public class SetPropertyDetailValuesMap extends MapProperty { - private final ISetProperty masterProperty; - private final IValueProperty detailProperty; +public class SetPropertyDetailValuesMap<S, M, T> extends MapProperty<S, M, T> { + private final ISetProperty<S, M> masterProperty; + private final IValueProperty<? super M, T> detailProperty; /** * @param masterProperty * @param detailProperty */ - public SetPropertyDetailValuesMap(ISetProperty masterProperty, - IValueProperty detailProperty) { + public SetPropertyDetailValuesMap(ISetProperty<S, M> masterProperty, + IValueProperty<? super M, T> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -53,32 +60,32 @@ public class SetPropertyDetailValuesMap extends MapProperty { return detailProperty.getValueType(); } - protected Map doGetMap(Object source) { - Set set = masterProperty.getSet(source); - Map map = new IdentityMap(); - for (Iterator it = set.iterator(); it.hasNext();) { - Object key = it.next(); + protected Map<M, T> doGetMap(S source) { + Set<M> set = masterProperty.getSet(source); + Map<M, T> map = new IdentityMap<M, T>(); + for (Iterator<M> it = set.iterator(); it.hasNext();) { + M key = it.next(); map.put(key, detailProperty.getValue(key)); } return map; } - protected void doUpdateMap(Object source, MapDiff diff) { + protected void doUpdateMap(S source, MapDiff<M, T> diff) { if (!diff.getAddedKeys().isEmpty()) throw new UnsupportedOperationException(toString() + " does not support entry additions"); //$NON-NLS-1$ if (!diff.getRemovedKeys().isEmpty()) throw new UnsupportedOperationException(toString() + " does not support entry removals"); //$NON-NLS-1$ - for (Iterator it = diff.getChangedKeys().iterator(); it.hasNext();) { - Object key = it.next(); - Object newValue = diff.getNewValue(key); + for (Iterator<M> it = diff.getChangedKeys().iterator(); it.hasNext();) { + M key = it.next(); + T newValue = diff.getNewValue(key); detailProperty.setValue(key, newValue); } } - public IObservableMap observe(Realm realm, Object source) { - IObservableSet masterSet; + public IObservableMap<M, T> observe(Realm realm, S source) { + IObservableSet<M> masterSet; ObservableTracker.setIgnore(true); try { @@ -87,13 +94,15 @@ public class SetPropertyDetailValuesMap extends MapProperty { ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterSet); + IObservableMap<M, T> detailMap = detailProperty + .observeDetail(masterSet); PropertyObservableUtil.cascadeDispose(detailMap, masterSet); return detailMap; } - public IObservableMap observeDetail(IObservableValue master) { - IObservableSet masterSet; + public <U extends S> IObservableMap<M, T> observeDetail( + IObservableValue<U> master) { + IObservableSet<M> masterSet; ObservableTracker.setIgnore(true); try { @@ -102,7 +111,8 @@ public class SetPropertyDetailValuesMap extends MapProperty { ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterSet); + IObservableMap<M, T> detailMap = detailProperty + .observeDetail(masterSet); PropertyObservableUtil.cascadeDispose(detailMap, masterSet); return detailMap; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailList.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailList.java index 095edf46..6658b05f 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailList.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailList.java @@ -24,19 +24,26 @@ import org.eclipse.core.databinding.property.list.ListProperty; import org.eclipse.core.databinding.property.value.IValueProperty; /** + * @param <S> + * type of the source object + * @param <M> + * type of the elements in the master list + * @param <T> + * type of the elements in the list, being the type of the value of + * the detail property * @since 3.3 * */ -public class ValuePropertyDetailList extends ListProperty { - private final IValueProperty masterProperty; - private final IListProperty detailProperty; +public class ValuePropertyDetailList<S, M, T> extends ListProperty<S, T> { + private final IValueProperty<S, M> masterProperty; + private final IListProperty<? super M, T> detailProperty; /** * @param masterProperty * @param detailProperty */ - public ValuePropertyDetailList(IValueProperty masterProperty, - IListProperty detailProperty) { + public ValuePropertyDetailList(IValueProperty<S, M> masterProperty, + IListProperty<? super M, T> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -45,23 +52,23 @@ public class ValuePropertyDetailList extends ListProperty { return detailProperty.getElementType(); } - protected List doGetList(Object source) { - Object masterValue = masterProperty.getValue(source); + protected List<T> doGetList(S source) { + M masterValue = masterProperty.getValue(source); return detailProperty.getList(masterValue); } - protected void doSetList(Object source, List list) { - Object masterValue = masterProperty.getValue(source); + protected void doSetList(S source, List<T> list) { + M masterValue = masterProperty.getValue(source); detailProperty.setList(masterValue, list); } - protected void doUpdateList(Object source, ListDiff diff) { - Object masterValue = masterProperty.getValue(source); + protected void doUpdateList(S source, ListDiff<T> diff) { + M masterValue = masterProperty.getValue(source); detailProperty.updateList(masterValue, diff); } - public IObservableList observe(Realm realm, Object source) { - IObservableValue masterValue; + public IObservableList<T> observe(Realm realm, S source) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -70,13 +77,15 @@ public class ValuePropertyDetailList extends ListProperty { ObservableTracker.setIgnore(false); } - IObservableList detailList = detailProperty.observeDetail(masterValue); + IObservableList<T> detailList = detailProperty + .observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailList, masterValue); return detailList; } - public IObservableList observeDetail(IObservableValue master) { - IObservableValue masterValue; + public <U extends S> IObservableList<T> observeDetail( + IObservableValue<U> master) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -85,7 +94,8 @@ public class ValuePropertyDetailList extends ListProperty { ObservableTracker.setIgnore(false); } - IObservableList detailList = detailProperty.observeDetail(masterValue); + IObservableList<T> detailList = detailProperty + .observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailList, masterValue); return detailList; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailMap.java index 1abdcece..993bc555 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailMap.java @@ -24,19 +24,28 @@ import org.eclipse.core.databinding.property.map.MapProperty; import org.eclipse.core.databinding.property.value.IValueProperty; /** + * @param <S> + * type of the source object + * @param <M> + * type of the property of the source object this type being the type + * that has the map as a property + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 3.3 * */ -public class ValuePropertyDetailMap extends MapProperty { - private final IValueProperty masterProperty; - private final IMapProperty detailProperty; +public class ValuePropertyDetailMap<S, M, K, V> extends MapProperty<S, K, V> { + private final IValueProperty<S, M> masterProperty; + private final IMapProperty<? super M, K, V> detailProperty; /** * @param masterProperty * @param detailProperty */ - public ValuePropertyDetailMap(IValueProperty masterProperty, - IMapProperty detailProperty) { + public ValuePropertyDetailMap(IValueProperty<S, M> masterProperty, + IMapProperty<? super M, K, V> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -49,23 +58,23 @@ public class ValuePropertyDetailMap extends MapProperty { return detailProperty.getValueType(); } - protected Map doGetMap(Object source) { - Object masterValue = masterProperty.getValue(source); + protected Map<K, V> doGetMap(S source) { + M masterValue = masterProperty.getValue(source); return detailProperty.getMap(masterValue); } - protected void doSetMap(Object source, Map map) { - Object masterValue = masterProperty.getValue(source); + protected void doSetMap(S source, Map<K, V> map) { + M masterValue = masterProperty.getValue(source); detailProperty.setMap(masterValue, map); } - protected void doUpdateMap(Object source, MapDiff diff) { - Object masterValue = masterProperty.getValue(source); + protected void doUpdateMap(S source, MapDiff<K, V> diff) { + M masterValue = masterProperty.getValue(source); detailProperty.updateMap(masterValue, diff); } - public IObservableMap observe(Realm realm, Object source) { - IObservableValue masterValue; + public IObservableMap<K, V> observe(Realm realm, S source) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -74,13 +83,15 @@ public class ValuePropertyDetailMap extends MapProperty { ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterValue); + IObservableMap<K, V> detailMap = detailProperty + .observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailMap, masterValue); return detailMap; } - public IObservableMap observeDetail(IObservableValue master) { - IObservableValue masterValue; + public <U extends S> IObservableMap<K, V> observeDetail( + IObservableValue<U> master) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -89,7 +100,8 @@ public class ValuePropertyDetailMap extends MapProperty { ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterValue); + IObservableMap<K, V> detailMap = detailProperty + .observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailMap, masterValue); return detailMap; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailSet.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailSet.java index 6e363fae..55e3e2df 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailSet.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailSet.java @@ -24,19 +24,27 @@ import org.eclipse.core.databinding.property.set.SetProperty; import org.eclipse.core.databinding.property.value.IValueProperty; /** + * @param <S> + * type of the source object + * @param <M> + * type of the property of the source object this type being the type + * that has the set as a property + * @param <T> + * type of the elements in the set, being the type of the value of + * the detail property * @since 3.3 * */ -public class ValuePropertyDetailSet extends SetProperty { - private IValueProperty masterProperty; - private ISetProperty detailProperty; +public class ValuePropertyDetailSet<S, M, T> extends SetProperty<S, T> { + private IValueProperty<S, M> masterProperty; + private ISetProperty<? super M, T> detailProperty; /** * @param masterProperty * @param detailProperty */ - public ValuePropertyDetailSet(IValueProperty masterProperty, - ISetProperty detailProperty) { + public ValuePropertyDetailSet(IValueProperty<S, M> masterProperty, + ISetProperty<? super M, T> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -45,23 +53,23 @@ public class ValuePropertyDetailSet extends SetProperty { return detailProperty.getElementType(); } - protected Set doGetSet(Object source) { - Object masterValue = masterProperty.getValue(source); + protected Set<T> doGetSet(S source) { + M masterValue = masterProperty.getValue(source); return detailProperty.getSet(masterValue); } - protected void doSetSet(Object source, Set set) { - Object masterValue = masterProperty.getValue(source); + protected void doSetSet(S source, Set<T> set) { + M masterValue = masterProperty.getValue(source); detailProperty.setSet(masterValue, set); } - protected void doUpdateSet(Object source, SetDiff diff) { - Object masterValue = masterProperty.getValue(source); + protected void doUpdateSet(S source, SetDiff<T> diff) { + M masterValue = masterProperty.getValue(source); detailProperty.updateSet(masterValue, diff); } - public IObservableSet observe(Realm realm, Object source) { - IObservableValue masterValue; + public IObservableSet<T> observe(Realm realm, S source) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -70,13 +78,14 @@ public class ValuePropertyDetailSet extends SetProperty { ObservableTracker.setIgnore(false); } - IObservableSet detailSet = detailProperty.observeDetail(masterValue); + IObservableSet<T> detailSet = detailProperty.observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailSet, masterValue); return detailSet; } - public IObservableSet observeDetail(IObservableValue master) { - IObservableValue masterValue; + public <U extends S> IObservableSet<T> observeDetail( + IObservableValue<U> master) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -85,7 +94,7 @@ public class ValuePropertyDetailSet extends SetProperty { ObservableTracker.setIgnore(false); } - IObservableSet detailSet = detailProperty.observeDetail(masterValue); + IObservableSet<T> detailSet = detailProperty.observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailSet, masterValue); return detailSet; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailValue.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailValue.java index 27cf02ce..c81ad87f 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailValue.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/ValuePropertyDetailValue.java @@ -22,20 +22,28 @@ import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.core.databinding.property.value.ValueProperty; /** + * @param <S> + * type of the source object + * @param <M> + * type of the property of the source object this type being the type + * that has the detail property as a property + * @param <T> + * type of this value property, being the same as the type of the + * value of the detail property * @since 1.2 * */ -public class ValuePropertyDetailValue extends ValueProperty implements - IValueProperty { - private IValueProperty masterProperty; - private IValueProperty detailProperty; +public class ValuePropertyDetailValue<S, M, T> extends ValueProperty<S, T> + implements IValueProperty<S, T> { + private IValueProperty<S, M> masterProperty; + private IValueProperty<? super M, T> detailProperty; /** * @param masterProperty * @param detailProperty */ - public ValuePropertyDetailValue(IValueProperty masterProperty, - IValueProperty detailProperty) { + public ValuePropertyDetailValue(IValueProperty<S, M> masterProperty, + IValueProperty<? super M, T> detailProperty) { this.masterProperty = masterProperty; this.detailProperty = detailProperty; } @@ -44,18 +52,18 @@ public class ValuePropertyDetailValue extends ValueProperty implements return detailProperty.getValueType(); } - protected Object doGetValue(Object source) { - Object masterValue = masterProperty.getValue(source); + protected T doGetValue(S source) { + M masterValue = masterProperty.getValue(source); return detailProperty.getValue(masterValue); } - protected void doSetValue(Object source, Object value) { - Object masterValue = masterProperty.getValue(source); + protected void doSetValue(S source, T value) { + M masterValue = masterProperty.getValue(source); detailProperty.setValue(masterValue, value); } - public IObservableValue observe(Realm realm, Object source) { - IObservableValue masterValue; + public IObservableValue<T> observe(Realm realm, S source) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -64,14 +72,15 @@ public class ValuePropertyDetailValue extends ValueProperty implements ObservableTracker.setIgnore(false); } - IObservableValue detailValue = detailProperty + IObservableValue<T> detailValue = detailProperty .observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailValue, masterValue); return detailValue; } - public IObservableValue observeDetail(IObservableValue master) { - IObservableValue masterValue; + public <V extends S> IObservableValue<T> observeDetail( + IObservableValue<V> master) { + IObservableValue<M> masterValue; ObservableTracker.setIgnore(true); try { @@ -80,14 +89,15 @@ public class ValuePropertyDetailValue extends ValueProperty implements ObservableTracker.setIgnore(false); } - IObservableValue detailValue = detailProperty + IObservableValue<T> detailValue = detailProperty .observeDetail(masterValue); PropertyObservableUtil.cascadeDispose(detailValue, masterValue); return detailValue; } - public IObservableList observeDetail(IObservableList master) { - IObservableList masterList; + public <V extends S> IObservableList<T> observeDetail( + IObservableList<V> master) { + IObservableList<M> masterList; ObservableTracker.setIgnore(true); try { @@ -96,13 +106,15 @@ public class ValuePropertyDetailValue extends ValueProperty implements ObservableTracker.setIgnore(false); } - IObservableList detailList = detailProperty.observeDetail(masterList); + IObservableList<T> detailList = detailProperty + .observeDetail(masterList); PropertyObservableUtil.cascadeDispose(detailList, masterList); return detailList; } - public IObservableMap observeDetail(IObservableSet master) { - IObservableMap masterMap; + public <V extends S> IObservableMap<V, T> observeDetail( + IObservableSet<V> master) { + IObservableMap<V, M> masterMap; ObservableTracker.setIgnore(true); try { @@ -111,13 +123,15 @@ public class ValuePropertyDetailValue extends ValueProperty implements ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterMap); + IObservableMap<V, T> detailMap = detailProperty + .observeDetail(masterMap); PropertyObservableUtil.cascadeDispose(detailMap, masterMap); return detailMap; } - public IObservableMap observeDetail(IObservableMap master) { - IObservableMap masterMap; + public <K, V extends S> IObservableMap<K, T> observeDetail( + IObservableMap<K, V> master) { + IObservableMap<K, M> masterMap; ObservableTracker.setIgnore(true); try { @@ -126,7 +140,8 @@ public class ValuePropertyDetailValue extends ValueProperty implements ObservableTracker.setIgnore(false); } - IObservableMap detailMap = detailProperty.observeDetail(masterMap); + IObservableMap<K, T> detailMap = detailProperty + .observeDetail(masterMap); PropertyObservableUtil.cascadeDispose(detailMap, masterMap); return detailMap; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SelfListProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SelfListProperty.java index 63a7137a..1d0e4441 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SelfListProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SelfListProperty.java @@ -20,10 +20,12 @@ import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.list.SimpleListProperty; /** + * @param <E> + * type of the elements in the list * @since 3.3 * */ -public class SelfListProperty extends SimpleListProperty { +public class SelfListProperty<E> extends SimpleListProperty<List<E>, E> { private final Object elementType; /** @@ -37,27 +39,28 @@ public class SelfListProperty extends SimpleListProperty { return elementType; } - protected List doGetList(Object source) { - return (List) source; + protected List<E> doGetList(List<E> source) { + return source; } - protected void doSetList(Object source, List list, ListDiff diff) { + protected void doSetList(List<E> source, List<E> list, ListDiff<E> diff) { doUpdateList(source, diff); } - protected void doUpdateList(Object source, ListDiff diff) { - diff.applyTo((List) source); + protected void doUpdateList(List<E> source, ListDiff<E> diff) { + diff.applyTo(source); } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<List<E>> adaptListener( + ISimplePropertyListener<ListDiff<E>> listener) { return null; // no listener API } - protected void doAddListener(Object source, INativePropertyListener listener) { + protected void doAddListener(Object source, + INativePropertyListener<List<E>> listener) { } protected void doRemoveListener(Object source, - INativePropertyListener listener) { + INativePropertyListener<List<E>> listener) { } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SimplePropertyObservableList.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SimplePropertyObservableList.java index 609ab05f..409c3147 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SimplePropertyObservableList.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/list/SimplePropertyObservableList.java @@ -27,28 +27,32 @@ import org.eclipse.core.databinding.observable.list.AbstractObservableList; import org.eclipse.core.databinding.observable.list.ListDiff; import org.eclipse.core.databinding.observable.list.ListDiffEntry; 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.list.SimpleListProperty; /** + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the list * @since 1.2 * */ -public class SimplePropertyObservableList extends AbstractObservableList - implements IPropertyObservable { - private Object source; - private SimpleListProperty property; +public class SimplePropertyObservableList<S, E> extends + AbstractObservableList<E> implements + IPropertyObservable<SimpleListProperty<S, E>> { + private S source; + private SimpleListProperty<S, E> property; private volatile boolean updating = false; private volatile int modCount = 0; - private INativePropertyListener listener; + private INativePropertyListener<S> listener; - private List cachedList; + private List<E> cachedList; private boolean stale; /** @@ -56,8 +60,8 @@ public class SimplePropertyObservableList extends AbstractObservableList * @param source * @param property */ - public SimplePropertyObservableList(Realm realm, Object source, - SimpleListProperty property) { + public SimplePropertyObservableList(Realm realm, S source, + SimpleListProperty<S, E> property) { super(realm); this.source = source; this.property = property; @@ -67,15 +71,15 @@ public class SimplePropertyObservableList extends AbstractObservableList if (!isDisposed()) { if (listener == null) { listener = property - .adaptListener(new ISimplePropertyListener() { + .adaptListener(new ISimplePropertyListener<ListDiff<E>>() { public void handleEvent( - final SimplePropertyEvent event) { + final SimplePropertyEvent<ListDiff<E>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { if (event.type == SimplePropertyEvent.CHANGE) { modCount++; - notifyIfChanged((ListDiff) event.diff); + notifyIfChanged(event.diff); } else if (event.type == SimplePropertyEvent.STALE && !stale) { stale = true; @@ -90,7 +94,7 @@ public class SimplePropertyObservableList extends AbstractObservableList getRealm().exec(new Runnable() { public void run() { - cachedList = new ArrayList(getList()); + cachedList = new ArrayList<E>(getList()); stale = false; if (listener != null) @@ -118,7 +122,7 @@ public class SimplePropertyObservableList extends AbstractObservableList // Queries - private List getList() { + private List<E> getList() { return property.getList(source); } @@ -131,12 +135,12 @@ public class SimplePropertyObservableList extends AbstractObservableList return getList().contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return getList().containsAll(c); } - public Object get(int index) { + public E get(int index) { getterCalled(); return getList().get(index); } @@ -161,14 +165,14 @@ public class SimplePropertyObservableList extends AbstractObservableList return getList().toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); return getList().toArray(a); } // Single change operations - private void updateList(List list, ListDiff diff) { + private void updateList(List<E> list, ListDiff<E> diff) { if (!diff.isEmpty()) { boolean wasUpdating = updating; updating = true; @@ -183,39 +187,39 @@ public class SimplePropertyObservableList extends AbstractObservableList } } - public boolean add(Object o) { + public boolean add(E o) { checkRealm(); - List list = getList(); + List<E> list = getList(); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(list - .size(), true, o)); + ListDiff<E> diff = Diffs.createListDiff(Diffs.createListDiffEntry( + list.size(), true, o)); updateList(list, diff); return true; } - public void add(int index, Object o) { + public void add(int index, E o) { checkRealm(); - List list = getList(); + List<E> list = getList(); if (index < 0 || index > list.size()) throw new IndexOutOfBoundsException(); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, - true, o)); + ListDiff<E> diff = Diffs.createListDiff(Diffs.createListDiffEntry( + index, true, o)); updateList(list, diff); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - return new Iterator() { + return new Iterator<E>() { int expectedModCount = modCount; - List list = new ArrayList(getList()); - ListIterator iterator = list.listIterator(); + List<E> list = new ArrayList<E>(getList()); + ListIterator<E> iterator = list.listIterator(); - Object lastElement = null; + E lastElement = null; int lastIndex = -1; public boolean hasNext() { @@ -224,10 +228,10 @@ public class SimplePropertyObservableList extends AbstractObservableList return iterator.hasNext(); } - public Object next() { + public E next() { getterCalled(); checkForComodification(); - Object next = lastElement = iterator.next(); + E next = lastElement = iterator.next(); lastIndex = iterator.previousIndex(); return next; } @@ -239,8 +243,8 @@ public class SimplePropertyObservableList extends AbstractObservableList throw new IllegalStateException(); iterator.remove(); // stay in sync - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( - lastIndex, false, lastElement)); + ListDiff<E> diff = Diffs.createListDiff(Diffs + .createListDiffEntry(lastIndex, false, lastElement)); updateList(list, diff); @@ -257,10 +261,10 @@ public class SimplePropertyObservableList extends AbstractObservableList }; } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { checkRealm(); - List list = getList(); + List<E> list = getList(); int size = list.size(); if (oldIndex < 0 || oldIndex >= size || newIndex < 0 || newIndex >= size) @@ -269,11 +273,11 @@ public class SimplePropertyObservableList extends AbstractObservableList if (oldIndex == newIndex) return list.get(oldIndex); - Object element = list.get(oldIndex); + E element = list.get(oldIndex); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( - oldIndex, false, element), Diffs.createListDiffEntry(newIndex, - true, element)); + ListDiff<E> diff = Diffs.createListDiff( + Diffs.createListDiffEntry(oldIndex, false, element), + Diffs.createListDiffEntry(newIndex, true, element)); updateList(list, diff); return element; @@ -282,31 +286,33 @@ public class SimplePropertyObservableList extends AbstractObservableList public boolean remove(Object o) { checkRealm(); - List list = getList(); + List<E> list = getList(); int index = list.indexOf(o); if (index == -1) return false; - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, - false, o)); + @SuppressWarnings("unchecked") + // o can only be of type E + ListDiff<E> diff = Diffs.createListDiff(Diffs.createListDiffEntry( + index, false, (E) o)); updateList(list, diff); return true; } - public ListIterator listIterator() { + public ListIterator<E> listIterator() { return listIterator(0); } - public ListIterator listIterator(final int index) { + public ListIterator<E> listIterator(final int index) { getterCalled(); - return new ListIterator() { + return new ListIterator<E>() { int expectedModCount = modCount; - List list = new ArrayList(getList()); - ListIterator iterator = list.listIterator(index); + List<E> list = new ArrayList<E>(getList()); + ListIterator<E> iterator = list.listIterator(index); - Object lastElement = null; + E lastElement = null; int lastIndex = -1; public boolean hasNext() { @@ -321,7 +327,7 @@ public class SimplePropertyObservableList extends AbstractObservableList return iterator.nextIndex(); } - public Object next() { + public E next() { getterCalled(); checkForComodification(); lastElement = iterator.next(); @@ -341,7 +347,7 @@ public class SimplePropertyObservableList extends AbstractObservableList return iterator.previousIndex(); } - public Object previous() { + public E previous() { getterCalled(); checkForComodification(); lastElement = iterator.previous(); @@ -349,13 +355,13 @@ public class SimplePropertyObservableList extends AbstractObservableList return lastElement; } - public void add(Object o) { + public void add(E o) { checkRealm(); checkForComodification(); int index = iterator.nextIndex(); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( - index, true, o)); + ListDiff<E> diff = Diffs.createListDiff(Diffs + .createListDiffEntry(index, true, o)); updateList(list, diff); iterator.add(o); // keep in sync @@ -365,13 +371,13 @@ public class SimplePropertyObservableList extends AbstractObservableList expectedModCount = modCount; } - public void set(Object o) { + public void set(E o) { checkRealm(); checkForComodification(); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( - lastIndex, false, lastElement), Diffs - .createListDiffEntry(lastIndex, true, o)); + ListDiff<E> diff = Diffs.createListDiff(Diffs + .createListDiffEntry(lastIndex, false, lastElement), + Diffs.createListDiffEntry(lastIndex, true, o)); updateList(list, diff); iterator.set(o); @@ -386,8 +392,8 @@ public class SimplePropertyObservableList extends AbstractObservableList if (lastIndex == -1) throw new IllegalStateException(); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry( - lastIndex, false, lastElement)); + ListDiff<E> diff = Diffs.createListDiff(Diffs + .createListDiffEntry(lastIndex, false, lastElement)); updateList(list, diff); iterator.remove(); // keep in sync @@ -404,33 +410,34 @@ public class SimplePropertyObservableList extends AbstractObservableList }; } - public Object remove(int index) { + public E remove(int index) { checkRealm(); - List list = getList(); - Object element = list.get(index); + List<E> list = getList(); + E element = list.get(index); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, - false, element)); + ListDiff<E> diff = Diffs.createListDiff(Diffs.createListDiffEntry( + index, false, element)); updateList(list, diff); return element; } - public Object set(int index, Object o) { + public E set(int index, E o) { checkRealm(); - List list = getList(); - Object oldElement = list.get(index); + List<E> list = getList(); + E oldElement = list.get(index); - ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index, - false, oldElement), Diffs.createListDiffEntry(index, true, o)); + ListDiff<E> diff = Diffs.createListDiff( + Diffs.createListDiffEntry(index, false, oldElement), + Diffs.createListDiffEntry(index, true, o)); updateList(list, diff); return oldElement; } - public List subList(int fromIndex, int toIndex) { + public List<E> subList(int fromIndex, int toIndex) { getterCalled(); return Collections.unmodifiableList(getList().subList(fromIndex, toIndex)); @@ -438,17 +445,17 @@ public class SimplePropertyObservableList extends AbstractObservableList // Bulk change operations - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { checkRealm(); if (c.isEmpty()) return false; - List list = getList(); + List<E> list = getList(); return addAll(list, list.size(), c); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { checkRealm(); if (c.isEmpty()) @@ -457,39 +464,39 @@ public class SimplePropertyObservableList extends AbstractObservableList return addAll(getList(), index, c); } - private boolean addAll(List list, int index, Collection c) { + private boolean addAll(List<E> list, int index, Collection<? extends E> c) { if (index < 0 || index > list.size()) throw new IndexOutOfBoundsException(); - ListDiffEntry[] entries = new ListDiffEntry[c.size()]; + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>( + c.size()); int offsetIndex = 0; - for (Iterator it = c.iterator(); it.hasNext();) { - Object element = it.next(); - entries[offsetIndex] = Diffs.createListDiffEntry(index - + offsetIndex, true, element); + for (E element : c) { + entries.add(Diffs.createListDiffEntry(index + offsetIndex, true, + element)); offsetIndex++; } - ListDiff diff = Diffs.createListDiff(entries); + ListDiff<E> diff = Diffs.createListDiff(entries); updateList(list, diff); return true; } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { checkRealm(); if (c.isEmpty()) return false; - List list = getList(); + List<E> list = getList(); if (list.isEmpty()) return false; - List entries = new ArrayList(); - for (ListIterator it = list.listIterator(); it.hasNext();) { + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>(); + for (ListIterator<E> it = list.listIterator(); it.hasNext();) { int index = it.nextIndex() - entries.size(); - Object element = it.next(); + E element = it.next(); if (c.contains(element)) { entries.add(Diffs.createListDiffEntry(index, false, element)); } @@ -498,17 +505,16 @@ public class SimplePropertyObservableList extends AbstractObservableList if (entries.isEmpty()) return false; - ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries - .toArray(new ListDiffEntry[entries.size()])); + ListDiff<E> diff = Diffs.createListDiff(entries); updateList(list, diff); return true; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { checkRealm(); - List list = getList(); + List<E> list = getList(); if (list.isEmpty()) return false; @@ -517,10 +523,10 @@ public class SimplePropertyObservableList extends AbstractObservableList return true; } - List entries = new ArrayList(); - for (ListIterator it = list.listIterator(); it.hasNext();) { + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>(); + for (ListIterator<E> it = list.listIterator(); it.hasNext();) { int index = it.nextIndex() - entries.size(); - Object element = it.next(); + E element = it.next(); if (!c.contains(element)) { entries.add(Diffs.createListDiffEntry(index, false, element)); } @@ -529,8 +535,7 @@ public class SimplePropertyObservableList extends AbstractObservableList if (entries.isEmpty()) return false; - ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries - .toArray(new ListDiffEntry[entries.size()])); + ListDiff<E> diff = Diffs.createListDiff(entries); updateList(list, diff); return true; @@ -539,27 +544,27 @@ public class SimplePropertyObservableList extends AbstractObservableList public void clear() { checkRealm(); - List list = getList(); + List<E> list = getList(); if (list.isEmpty()) return; - List entries = new ArrayList(); - for (ListIterator it = list.listIterator(list.size()); it.hasPrevious();) { + List<ListDiffEntry<E>> entries = new ArrayList<ListDiffEntry<E>>(); + for (ListIterator<E> it = list.listIterator(list.size()); it + .hasPrevious();) { // always report 0 as the remove index int index = it.previousIndex(); - Object element = it.previous(); + E element = it.previous(); entries.add(Diffs.createListDiffEntry(index, false, element)); } - ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries - .toArray(new ListDiffEntry[entries.size()])); + ListDiff<E> diff = Diffs.createListDiff(entries); updateList(list, diff); } - private void notifyIfChanged(ListDiff diff) { + private void notifyIfChanged(ListDiff<E> diff) { if (hasListeners()) { - List oldList = cachedList; - List newList = cachedList = new ArrayList(getList()); + List<E> oldList = cachedList; + List<E> newList = cachedList = new ArrayList<E>(getList()); if (diff == null) diff = Diffs.computeListDiff(oldList, newList); if (!diff.isEmpty() || stale) { @@ -588,7 +593,7 @@ public class SimplePropertyObservableList extends AbstractObservableList return source; } - public IProperty getProperty() { + public SimpleListProperty<S, E> getProperty() { return property; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SelfMapProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SelfMapProperty.java index c6936076..5bb5005a 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SelfMapProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SelfMapProperty.java @@ -20,10 +20,15 @@ import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.map.SimpleMapProperty; /** + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 3.3 * */ -public final class SelfMapProperty extends SimpleMapProperty { +public final class SelfMapProperty<K, V> extends + SimpleMapProperty<Map<K, V>, K, V> { private final Object keyType; private final Object valueType; @@ -44,27 +49,28 @@ public final class SelfMapProperty extends SimpleMapProperty { return valueType; } - protected Map doGetMap(Object source) { - return (Map) source; + protected Map<K, V> doGetMap(Map<K, V> source) { + return source; } - protected void doSetMap(Object source, Map map, MapDiff diff) { + protected void doSetMap(Map<K, V> source, Map<K, V> map, MapDiff<K, V> diff) { doUpdateMap(source, diff); } - protected void doUpdateMap(Object source, MapDiff diff) { - diff.applyTo((Map) source); + protected void doUpdateMap(Map<K, V> source, MapDiff<K, V> diff) { + diff.applyTo(source); } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<Map<K, V>> adaptListener( + ISimplePropertyListener<MapDiff<K, V>> listener) { return null; // no listener API } - protected void doAddListener(Object source, INativePropertyListener listener) { + protected void doAddListener(Object source, + INativePropertyListener<Map<K, V>> listener) { } protected void doRemoveListener(Object source, - INativePropertyListener listener) { + INativePropertyListener<Map<K, V>> listener) { } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SimplePropertyObservableMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SimplePropertyObservableMap.java index df7fd0d8..2fe2cb19 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SimplePropertyObservableMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/map/SimplePropertyObservableMap.java @@ -29,27 +29,33 @@ import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.map.AbstractObservableMap; import org.eclipse.core.databinding.observable.map.MapDiff; 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.map.SimpleMapProperty; /** + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 */ -public class SimplePropertyObservableMap extends AbstractObservableMap - implements IPropertyObservable { - private Object source; - private SimpleMapProperty property; +public class SimplePropertyObservableMap<S, K, V> extends + AbstractObservableMap<K, V> implements + IPropertyObservable<SimpleMapProperty<S, K, V>> { + private S source; + private SimpleMapProperty<S, K, V> property; private volatile boolean updating = false; private volatile int modCount = 0; - private INativePropertyListener listener; + private INativePropertyListener<S> listener; - private Map cachedMap; + private Map<K, V> cachedMap; private boolean stale; /** @@ -57,8 +63,8 @@ public class SimplePropertyObservableMap extends AbstractObservableMap * @param source * @param property */ - public SimplePropertyObservableMap(Realm realm, Object source, - SimpleMapProperty property) { + public SimplePropertyObservableMap(Realm realm, S source, + SimpleMapProperty<S, K, V> property) { super(realm); this.source = source; this.property = property; @@ -80,15 +86,15 @@ public class SimplePropertyObservableMap extends AbstractObservableMap if (!isDisposed()) { if (listener == null) { listener = property - .adaptListener(new ISimplePropertyListener() { + .adaptListener(new ISimplePropertyListener<MapDiff<K, V>>() { public void handleEvent( - final SimplePropertyEvent event) { + final SimplePropertyEvent<MapDiff<K, V>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { if (event.type == SimplePropertyEvent.CHANGE) { modCount++; - notifyIfChanged((MapDiff) event.diff); + notifyIfChanged(event.diff); } else if (event.type == SimplePropertyEvent.STALE && !stale) { stale = true; @@ -103,7 +109,7 @@ public class SimplePropertyObservableMap extends AbstractObservableMap getRealm().exec(new Runnable() { public void run() { - cachedMap = new HashMap(getMap()); + cachedMap = new HashMap<K, V>(getMap()); stale = false; if (listener != null) @@ -124,13 +130,13 @@ public class SimplePropertyObservableMap extends AbstractObservableMap // Queries - private Map getMap() { + private Map<K, V> getMap() { return property.getMap(source); } // Single change operations - private void updateMap(Map map, MapDiff diff) { + private void updateMap(Map<K, V> map, MapDiff<K, V> diff) { if (!diff.isEmpty()) { boolean wasUpdating = updating; updating = true; @@ -147,13 +153,13 @@ public class SimplePropertyObservableMap extends AbstractObservableMap private EntrySet es = new EntrySet(); - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { getterCalled(); return es; } - private class EntrySet extends AbstractSet { - public Iterator iterator() { + private class EntrySet extends AbstractSet<Map.Entry<K, V>> { + public Iterator<Map.Entry<K, V>> iterator() { return new EntrySetIterator(); } @@ -162,11 +168,11 @@ public class SimplePropertyObservableMap extends AbstractObservableMap } } - private class EntrySetIterator implements Iterator { + private class EntrySetIterator implements Iterator<Map.Entry<K, V>> { private volatile int expectedModCount = modCount; - Map map = new HashMap(getMap()); - Iterator iterator = map.entrySet().iterator(); - Map.Entry last = null; + Map<K, V> map = new HashMap<K, V>(getMap()); + Iterator<Map.Entry<K, V>> iterator = map.entrySet().iterator(); + Map.Entry<K, V> last = null; public boolean hasNext() { getterCalled(); @@ -174,10 +180,10 @@ public class SimplePropertyObservableMap extends AbstractObservableMap return iterator.hasNext(); } - public Object next() { + public Map.Entry<K, V> next() { getterCalled(); checkForComodification(); - last = (Map.Entry) iterator.next(); + last = iterator.next(); return last; } @@ -185,7 +191,7 @@ public class SimplePropertyObservableMap extends AbstractObservableMap getterCalled(); checkForComodification(); - MapDiff diff = Diffs.createMapDiffSingleRemove(last.getKey(), + MapDiff<K, V> diff = Diffs.createMapDiffSingleRemove(last.getKey(), last.getValue()); updateMap(map, diff); @@ -201,7 +207,7 @@ public class SimplePropertyObservableMap extends AbstractObservableMap } } - public Set keySet() { + public Set<K> keySet() { getterCalled(); // AbstractMap depends on entrySet() to fulfil keySet() API, so all // getterCalled() and comodification checks will still be handled @@ -214,22 +220,22 @@ public class SimplePropertyObservableMap extends AbstractObservableMap return getMap().containsKey(key); } - public Object get(Object key) { + public V get(Object key) { getterCalled(); return getMap().get(key); } - public Object put(Object key, Object value) { + public V put(K key, V value) { checkRealm(); - Map map = getMap(); + Map<K, V> map = getMap(); boolean add = !map.containsKey(key); - Object oldValue = map.get(key); + V oldValue = map.get(key); - MapDiff diff; + MapDiff<K, V> diff; if (add) diff = Diffs.createMapDiffSingleAdd(key, value); else @@ -240,19 +246,18 @@ public class SimplePropertyObservableMap extends AbstractObservableMap return oldValue; } - public void putAll(Map m) { + public void putAll(Map<? extends K, ? extends V> m) { checkRealm(); - Map map = getMap(); + Map<K, V> map = getMap(); - Map oldValues = new HashMap(); - Map newValues = new HashMap(); - Set changedKeys = new HashSet(); - Set addedKeys = new HashSet(); - for (Iterator it = m.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Object key = entry.getKey(); - Object newValue = entry.getValue(); + Map<K, V> oldValues = new HashMap<K, V>(); + Map<K, V> newValues = new HashMap<K, V>(); + Set<K> changedKeys = new HashSet<K>(); + Set<K> addedKeys = new HashSet<K>(); + for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) { + K key = entry.getKey(); + V newValue = entry.getValue(); if (map.containsKey(key)) { changedKeys.add(key); oldValues.put(key, map.get(key)); @@ -262,21 +267,24 @@ public class SimplePropertyObservableMap extends AbstractObservableMap newValues.put(key, newValue); } - MapDiff diff = Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET, - changedKeys, oldValues, newValues); + MapDiff<K, V> diff = Diffs.createMapDiff(addedKeys, + Collections.<K> emptySet(), changedKeys, oldValues, newValues); updateMap(map, diff); } - public Object remove(Object key) { + public V remove(Object key) { checkRealm(); - Map map = getMap(); + Map<K, V> map = getMap(); if (!map.containsKey(key)) return null; - Object oldValue = map.get(key); + V oldValue = map.get(key); - MapDiff diff = Diffs.createMapDiffSingleRemove(key, oldValue); + @SuppressWarnings("unchecked") + // if we contain this key, then it is of + // type K + MapDiff<K, V> diff = Diffs.createMapDiffSingleRemove((K) key, oldValue); updateMap(map, diff); return oldValue; @@ -285,25 +293,26 @@ public class SimplePropertyObservableMap extends AbstractObservableMap public void clear() { getterCalled(); - Map map = getMap(); + Map<K, V> map = getMap(); if (map.isEmpty()) return; - MapDiff diff = Diffs.createMapDiffRemoveAll(new HashMap(map)); + MapDiff<K, V> diff = Diffs + .createMapDiffRemoveAll(new HashMap<K, V>(map)); updateMap(map, diff); } - public Collection values() { + public Collection<V> values() { getterCalled(); // AbstractMap depends on entrySet() to fulfil values() API, so all // getterCalled() and comodification checks will still be handled return super.values(); } - private void notifyIfChanged(MapDiff diff) { + private void notifyIfChanged(MapDiff<K, V> diff) { if (hasListeners()) { - Map oldMap = cachedMap; - Map newMap = cachedMap = new HashMap(getMap()); + Map<K, V> oldMap = cachedMap; + Map<K, V> newMap = cachedMap = new HashMap<K, V>(getMap()); if (diff == null) diff = Diffs.computeMapDiff(oldMap, newMap); if (!diff.isEmpty() || stale) { @@ -322,7 +331,7 @@ public class SimplePropertyObservableMap extends AbstractObservableMap return source; } - public IProperty getProperty() { + public SimpleMapProperty<S, K, V> getProperty() { return property; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SelfSetProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SelfSetProperty.java index dd76d505..839dde1d 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SelfSetProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SelfSetProperty.java @@ -20,10 +20,12 @@ import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.set.SimpleSetProperty; /** + * @param <E> + * type of the elements in the set * @since 3.3 * */ -public final class SelfSetProperty extends SimpleSetProperty { +public final class SelfSetProperty<E> extends SimpleSetProperty<Set<E>, E> { private final Object elementType; /** @@ -37,23 +39,24 @@ public final class SelfSetProperty extends SimpleSetProperty { return elementType; } - protected Set doGetSet(Object source) { - return (Set) source; + protected Set<E> doGetSet(Set<E> source) { + return source; } - protected void doSetSet(Object source, Set set, SetDiff diff) { - diff.applyTo((Set) source); + protected void doSetSet(Set<E> source, Set<E> set, SetDiff<E> diff) { + diff.applyTo(source); } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<Set<E>> adaptListener( + ISimplePropertyListener<SetDiff<E>> listener) { return null; // no listener API } - protected void doAddListener(Object source, INativePropertyListener listener) { + protected void doAddListener(Object source, + INativePropertyListener<Set<E>> listener) { } - protected void doRemoveListener(Object source, - INativePropertyListener listener) { + protected void doRemoveListener(Set<E> source, + INativePropertyListener<Set<E>> listener) { } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SimplePropertyObservableSet.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SimplePropertyObservableSet.java index 4e851ab8..b989f654 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SimplePropertyObservableSet.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/set/SimplePropertyObservableSet.java @@ -24,28 +24,31 @@ import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.set.AbstractObservableSet; import org.eclipse.core.databinding.observable.set.SetDiff; 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.set.SimpleSetProperty; /** + * @param <S> + * type of the source object + * @param <E> + * type of the elements in the set * @since 1.2 * */ -public class SimplePropertyObservableSet extends AbstractObservableSet - implements IPropertyObservable { - private Object source; - private SimpleSetProperty property; +public class SimplePropertyObservableSet<S, E> extends AbstractObservableSet<E> + implements IPropertyObservable<SimpleSetProperty<S, E>> { + private S source; + private SimpleSetProperty<S, E> property; private volatile boolean updating = false; private volatile int modCount = 0; - private INativePropertyListener listener; + private INativePropertyListener<S> listener; - private Set cachedSet; + private Set<E> cachedSet; private boolean stale; /** @@ -53,8 +56,8 @@ public class SimplePropertyObservableSet extends AbstractObservableSet * @param source * @param property */ - public SimplePropertyObservableSet(Realm realm, Object source, - SimpleSetProperty property) { + public SimplePropertyObservableSet(Realm realm, S source, + SimpleSetProperty<S, E> property) { super(realm); this.source = source; this.property = property; @@ -64,15 +67,15 @@ public class SimplePropertyObservableSet extends AbstractObservableSet if (!isDisposed()) { if (listener == null) { listener = property - .adaptListener(new ISimplePropertyListener() { + .adaptListener(new ISimplePropertyListener<SetDiff<E>>() { public void handleEvent( - final SimplePropertyEvent event) { + final SimplePropertyEvent<SetDiff<E>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { if (event.type == SimplePropertyEvent.CHANGE) { modCount++; - notifyIfChanged((SetDiff) event.diff); + notifyIfChanged(event.diff); } else if (event.type == SimplePropertyEvent.STALE && !stale) { stale = true; @@ -87,7 +90,7 @@ public class SimplePropertyObservableSet extends AbstractObservableSet getRealm().exec(new Runnable() { public void run() { - cachedSet = new HashSet(getSet()); + cachedSet = new HashSet<E>(getSet()); stale = false; if (listener != null) @@ -106,7 +109,7 @@ public class SimplePropertyObservableSet extends AbstractObservableSet stale = false; } - protected Set getWrappedSet() { + protected Set<E> getWrappedSet() { return getSet(); } @@ -116,7 +119,7 @@ public class SimplePropertyObservableSet extends AbstractObservableSet // Queries - private Set getSet() { + private Set<E> getSet() { return property.getSet(source); } @@ -125,7 +128,7 @@ public class SimplePropertyObservableSet extends AbstractObservableSet return getSet().contains(o); } - public boolean containsAll(Collection c) { + public boolean containsAll(Collection<?> c) { getterCalled(); return getSet().containsAll(c); } @@ -140,14 +143,14 @@ public class SimplePropertyObservableSet extends AbstractObservableSet return getSet().toArray(); } - public Object[] toArray(Object[] a) { + public <T> T[] toArray(T[] a) { getterCalled(); return getSet().toArray(a); } // Single change operations - private void updateSet(Set set, SetDiff diff) { + private void updateSet(Set<E> set, SetDiff<E> diff) { if (!diff.isEmpty()) { boolean wasUpdating = updating; updating = true; @@ -162,27 +165,27 @@ public class SimplePropertyObservableSet extends AbstractObservableSet } } - public boolean add(Object o) { + public boolean add(E o) { checkRealm(); - Set set = getSet(); + Set<E> set = getSet(); if (set.contains(o)) return false; - SetDiff diff = Diffs.createSetDiff(Collections.singleton(o), - Collections.EMPTY_SET); + SetDiff<E> diff = Diffs.createSetDiff(Collections.singleton(o), + Collections.<E> emptySet()); updateSet(set, diff); return true; } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - return new Iterator() { + return new Iterator<E>() { int expectedModCount = modCount; - Set set = new HashSet(getSet()); - Iterator iterator = set.iterator(); - Object last = null; + Set<E> set = new HashSet<E>(getSet()); + Iterator<E> iterator = set.iterator(); + E last = null; public boolean hasNext() { getterCalled(); @@ -190,7 +193,7 @@ public class SimplePropertyObservableSet extends AbstractObservableSet return iterator.hasNext(); } - public Object next() { + public E next() { getterCalled(); checkForComodification(); last = iterator.next(); @@ -201,8 +204,9 @@ public class SimplePropertyObservableSet extends AbstractObservableSet checkRealm(); checkForComodification(); - SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, - Collections.singleton(last)); + SetDiff<E> diff = Diffs + .createSetDiff(Collections.<E> emptySet(), + Collections.singleton(last)); updateSet(set, diff); iterator.remove(); // stay in sync @@ -221,12 +225,14 @@ public class SimplePropertyObservableSet extends AbstractObservableSet public boolean remove(Object o) { getterCalled(); - Set set = getSet(); + Set<E> set = getSet(); if (!set.contains(o)) return false; - SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, Collections - .singleton(o)); + @SuppressWarnings("unchecked") + // if o is contained, it is an E + SetDiff<E> diff = Diffs.createSetDiff(Collections.<E> emptySet(), + Collections.singleton((E) o)); updateSet(set, diff); return true; @@ -234,54 +240,60 @@ public class SimplePropertyObservableSet extends AbstractObservableSet // Bulk change operations - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { getterCalled(); if (c.isEmpty()) return false; - Set set = getSet(); + Set<E> set = getSet(); if (set.containsAll(c)) return false; - Set additions = new HashSet(c); + Set<E> additions = new HashSet<E>(c); additions.removeAll(set); if (additions.isEmpty()) return false; - SetDiff diff = Diffs.createSetDiff(additions, Collections.EMPTY_SET); + SetDiff<E> diff = Diffs.createSetDiff(additions, + Collections.<E> emptySet()); updateSet(set, diff); return true; } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { getterCalled(); if (c.isEmpty()) return false; - Set set = getSet(); + Set<E> set = getSet(); if (set.isEmpty()) return false; - Set removals = new HashSet(c); + Set<Object> removals = new HashSet<Object>(c); removals.retainAll(set); + @SuppressWarnings("unchecked") + // because we have removed everything that + // is not an E + Set<E> typedRemovals = (Set<E>) removals; if (removals.isEmpty()) return false; - SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals); + SetDiff<E> diff = Diffs.createSetDiff(Collections.<E> emptySet(), + typedRemovals); updateSet(set, diff); return true; } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { getterCalled(); - Set set = getSet(); + Set<E> set = getSet(); if (set.isEmpty()) return false; @@ -290,13 +302,14 @@ public class SimplePropertyObservableSet extends AbstractObservableSet return true; } - Set removals = new HashSet(set); + Set<E> removals = new HashSet<E>(set); removals.removeAll(c); if (removals.isEmpty()) return false; - SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals); + SetDiff<E> diff = Diffs.createSetDiff(Collections.<E> emptySet(), + removals); updateSet(set, diff); return true; @@ -305,18 +318,18 @@ public class SimplePropertyObservableSet extends AbstractObservableSet public void clear() { getterCalled(); - Set set = getSet(); + Set<E> set = getSet(); if (set.isEmpty()) return; - SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, set); + SetDiff<E> diff = Diffs.createSetDiff(Collections.<E> emptySet(), set); updateSet(set, diff); } - private void notifyIfChanged(SetDiff diff) { + private void notifyIfChanged(SetDiff<E> diff) { if (hasListeners()) { - Set oldSet = cachedSet; - Set newSet = cachedSet = new HashSet(getSet()); + Set<E> oldSet = cachedSet; + Set<E> newSet = cachedSet = new HashSet<E>(getSet()); if (diff == null) diff = Diffs.computeSetDiff(oldSet, newSet); if (!diff.isEmpty() || stale) { @@ -345,7 +358,7 @@ public class SimplePropertyObservableSet extends AbstractObservableSet return source; } - public IProperty getProperty() { + public SimpleSetProperty<S, E> getProperty() { return property; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java index af820e5f..b5b37d22 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/DelegatingCache.java @@ -34,35 +34,35 @@ import org.eclipse.core.internal.databinding.identity.IdentityObservableSet; * @since 3.3 * */ -abstract class DelegatingCache { +abstract class DelegatingCache<S, K extends S, V> { private Realm realm; - private DelegatingValueProperty detailProperty; - private IObservableSet elements; - private Map delegateCaches; + private DelegatingValueProperty<S, V> detailProperty; + private IObservableSet<K> elements; + private Map<IValueProperty<S, V>, DelegateCache> delegateCaches; - private class DelegateCache implements IMapChangeListener { - private final IValueProperty delegate; - private final IObservableSet masterElements; - private final IObservableMap masterElementValues; - private final Map cachedValues; + private class DelegateCache implements IMapChangeListener<K, V> { + private final IValueProperty<S, V> delegate; + private final IObservableSet<K> masterElements; + private final IObservableMap<K, V> masterElementValues; + private final Map<K, V> cachedValues; - DelegateCache(IValueProperty delegate) { + DelegateCache(IValueProperty<S, V> delegate) { this.delegate = delegate; ObservableTracker.setIgnore(true); try { - this.masterElements = new IdentityObservableSet(realm, elements + this.masterElements = new IdentityObservableSet<K>(realm, elements .getElementType()); this.masterElementValues = delegate .observeDetail(masterElements); } finally { ObservableTracker.setIgnore(false); } - this.cachedValues = new IdentityMap(); + this.cachedValues = new IdentityMap<K, V>(); masterElementValues.addMapChangeListener(this); } - void add(Object masterElement) { + void add(K masterElement) { boolean wasEmpty = masterElements.isEmpty(); masterElements.add(masterElement); @@ -80,13 +80,12 @@ abstract class DelegatingCache { dispose(); } - Object get(Object masterElement) { + V get(Object masterElement) { return cachedValues.get(masterElement); } - Object put(Object masterElement, Object detailValue) { - Object oldValue = masterElementValues.put(masterElement, - detailValue); + V put(K masterElement, V detailValue) { + V oldValue = masterElementValues.put(masterElement, detailValue); notifyIfChanged(masterElement); return oldValue; } @@ -95,23 +94,22 @@ abstract class DelegatingCache { return cachedValues.containsValue(detailValue); } - public void handleMapChange(MapChangeEvent event) { - Set changedKeys = event.diff.getChangedKeys(); - for (Iterator it = changedKeys.iterator(); it.hasNext();) + public void handleMapChange(MapChangeEvent<K, V> event) { + Set<K> changedKeys = event.diff.getChangedKeys(); + for (Iterator<K> it = changedKeys.iterator(); it.hasNext();) notifyIfChanged(it.next()); } - private void notifyIfChanged(Object masterElement) { - Object oldValue = cachedValues.get(masterElement); - Object newValue = masterElementValues.get(masterElement); + private void notifyIfChanged(K masterElement) { + V oldValue = cachedValues.get(masterElement); + V newValue = masterElementValues.get(masterElement); if (oldValue != newValue) { cachedValues.put(masterElement, newValue); handleValueChange(masterElement, oldValue, newValue); } } - void handleValueChange(Object masterElement, Object oldValue, - Object newValue) { + void handleValueChange(K masterElement, V oldValue, V newValue) { DelegatingCache.this.handleValueChange(masterElement, oldValue, newValue); } @@ -124,30 +122,30 @@ abstract class DelegatingCache { } } - DelegatingCache(Realm realm, DelegatingValueProperty detailProperty) { + DelegatingCache(Realm realm, DelegatingValueProperty<S, V> detailProperty) { this.realm = realm; this.detailProperty = detailProperty; ObservableTracker.setIgnore(true); try { - this.elements = new IdentityObservableSet(realm, null); + this.elements = new IdentityObservableSet<K>(realm, null); } finally { ObservableTracker.setIgnore(false); } - this.delegateCaches = new IdentityMap(); + this.delegateCaches = new IdentityMap<IValueProperty<S, V>, DelegateCache>(); - elements.addSetChangeListener(new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { - for (Iterator it = event.diff.getRemovals().iterator(); it + elements.addSetChangeListener(new ISetChangeListener<K>() { + public void handleSetChange(SetChangeEvent<K> event) { + for (Iterator<K> it = event.diff.getRemovals().iterator(); it .hasNext();) { - Object element = it.next(); + K element = it.next(); getCache(element).remove(element); } - for (Iterator it = event.diff.getAdditions().iterator(); it + for (Iterator<K> it = event.diff.getAdditions().iterator(); it .hasNext();) { - Object element = it.next(); + K element = it.next(); getCache(element).add(element); } } @@ -155,40 +153,46 @@ abstract class DelegatingCache { } private DelegateCache getCache(Object masterElement) { - IValueProperty delegate = detailProperty.getDelegate(masterElement); + // NOTE: This is unsafe. This has to remain typed as Object because + // Map.get(x) has x as being an object, and this call is forwarded here. + // The likeliest problem is a ClassCastException in the ValueProperty. + // But this is what we would have gotten anyway without generics, only + // the cast would be explicit. + @SuppressWarnings("unchecked") IValueProperty<S, V> delegate = detailProperty + .getDelegate((S) masterElement); if (delegateCaches.containsKey(delegate)) { - return (DelegateCache) delegateCaches.get(delegate); + return delegateCaches.get(delegate); } return new DelegateCache(delegate); } - Object get(Object element) { + V get(Object element) { return getCache(element).get(element); } - Object put(Object element, Object value) { + V put(K element, V value) { return getCache(element).put(element, value); } boolean containsValue(Object value) { - for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) { - DelegateCache cache = (DelegateCache) it.next(); + for (Iterator<DelegateCache> it = delegateCaches.values().iterator(); it + .hasNext();) { + DelegateCache cache = it.next(); if (cache.containsValue(value)) return true; } return false; } - void addAll(Collection elements) { + void addAll(Collection<? extends K> elements) { this.elements.addAll(elements); } - void retainAll(Collection elements) { + void retainAll(Collection<?> elements) { this.elements.retainAll(elements); } - abstract void handleValueChange(Object masterElement, Object oldValue, - Object newValue); + abstract void handleValueChange(K masterElement, V oldValue, V newValue); void dispose() { if (elements != null) { @@ -198,8 +202,9 @@ abstract class DelegatingCache { } if (delegateCaches != null) { - for (Iterator it = delegateCaches.values().iterator(); it.hasNext();) { - DelegateCache cache = (DelegateCache) it.next(); + for (Iterator<DelegateCache> it = delegateCaches.values() + .iterator(); it.hasNext();) { + DelegateCache cache = it.next(); cache.dispose(); } delegateCaches.clear(); diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java index e436263c..6807f9eb 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListDelegatingValueObservableList.java @@ -29,47 +29,53 @@ import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.ListChangeEvent; import org.eclipse.core.databinding.observable.list.ListDiff; import org.eclipse.core.databinding.observable.list.ListDiffEntry; -import org.eclipse.core.databinding.property.IProperty; import org.eclipse.core.databinding.property.IPropertyObservable; import org.eclipse.core.databinding.property.value.DelegatingValueProperty; /** + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property + * @param <E> + * type of the elements in the list * @since 1.2 */ -public class ListDelegatingValueObservableList extends AbstractObservableList - implements IPropertyObservable { - private IObservableList masterList; - private DelegatingValueProperty detailProperty; - private DelegatingCache cache; - - private IListChangeListener masterListener = new IListChangeListener() { - public void handleListChange(ListChangeEvent event) { +public class ListDelegatingValueObservableList<S, T extends S, E> extends + AbstractObservableList<E> implements + IPropertyObservable<DelegatingValueProperty<S, E>> { + private IObservableList<T> masterList; + private DelegatingValueProperty<S, E> detailProperty; + private DelegatingCache<S, T, E> cache; + + private IListChangeListener<T> masterListener = new IListChangeListener<T>() { + public void handleListChange(ListChangeEvent<T> event) { if (isDisposed()) return; cache.addAll(masterList); // Need both obsolete and new elements to convert diff - ListDiff diff = convertDiff(event.diff); + ListDiff<E> diff = convertDiff(event.diff); cache.retainAll(masterList); fireListChange(diff); } - private ListDiff convertDiff(ListDiff diff) { + private ListDiff<E> convertDiff(ListDiff<T> diff) { // Convert diff to detail value - ListDiffEntry[] masterEntries = diff.getDifferences(); - ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; - for (int i = 0; i < masterEntries.length; i++) { - ListDiffEntry masterDifference = masterEntries[i]; + List<ListDiffEntry<T>> masterEntries = diff.getDifferencesAsList(); + List<ListDiffEntry<E>> detailEntries = new ArrayList<ListDiffEntry<E>>( + masterEntries.size()); + for (ListDiffEntry<T> masterDifference : masterEntries) { int index = masterDifference.getPosition(); boolean addition = masterDifference.isAddition(); - Object masterElement = masterDifference.getElement(); - Object detailValue = cache.get(masterElement); + T masterElement = masterDifference.getElement(); + E detailValue = cache.get(masterElement); - detailEntries[i] = Diffs.createListDiffEntry(index, addition, - detailValue); + detailEntries.add(Diffs.createListDiffEntry(index, addition, + detailValue)); } return Diffs.createListDiff(detailEntries); } @@ -85,14 +91,13 @@ public class ListDelegatingValueObservableList extends AbstractObservableList * @param masterList * @param valueProperty */ - public ListDelegatingValueObservableList(IObservableList masterList, - DelegatingValueProperty valueProperty) { + public ListDelegatingValueObservableList(IObservableList<T> masterList, + DelegatingValueProperty<S, E> valueProperty) { super(masterList.getRealm()); this.masterList = masterList; this.detailProperty = valueProperty; - this.cache = new DelegatingCache(getRealm(), valueProperty) { - void handleValueChange(Object masterElement, Object oldValue, - Object newValue) { + this.cache = new DelegatingCache<S, T, E>(getRealm(), valueProperty) { + void handleValueChange(T masterElement, E oldValue, E newValue) { fireListChange(indicesOf(masterElement), oldValue, newValue); } }; @@ -111,9 +116,9 @@ public class ListDelegatingValueObservableList extends AbstractObservableList ObservableTracker.getterCalled(this); } - public Object get(int index) { + public E get(int index) { getterCalled(); - Object masterElement = masterList.get(index); + T masterElement = masterList.get(index); return cache.get(masterElement); } @@ -121,11 +126,11 @@ public class ListDelegatingValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends E> c) { throw new UnsupportedOperationException(); } @@ -144,19 +149,19 @@ public class ListDelegatingValueObservableList extends AbstractObservableList return masterList.isStale(); } - public Iterator iterator() { + public Iterator<E> iterator() { getterCalled(); - return new Iterator() { - Iterator it = masterList.iterator(); + return new Iterator<E>() { + Iterator<T> it = masterList.iterator(); public boolean hasNext() { getterCalled(); return it.hasNext(); } - public Object next() { + public E next() { getterCalled(); - Object masterElement = it.next(); + T masterElement = it.next(); return cache.get(masterElement); } @@ -166,7 +171,7 @@ public class ListDelegatingValueObservableList extends AbstractObservableList }; } - public Object move(int oldIndex, int newIndex) { + public E move(int oldIndex, int newIndex) { throw new UnsupportedOperationException(); } @@ -174,11 +179,11 @@ public class ListDelegatingValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } @@ -192,14 +197,15 @@ public class ListDelegatingValueObservableList extends AbstractObservableList return result; } - public Object[] toArray(Object[] a) { + @SuppressWarnings("unchecked") + public <U> U[] toArray(U[] a) { getterCalled(); Object[] masterElements = masterList.toArray(); if (a.length < masterElements.length) - a = (Object[]) Array.newInstance(a.getClass().getComponentType(), + a = (U[]) Array.newInstance(a.getClass().getComponentType(), masterElements.length); for (int i = 0; i < masterElements.length; i++) { - a[i] = cache.get(masterElements[i]); + a[i] = (U) cache.get(masterElements[i]); } return a; } @@ -212,16 +218,16 @@ public class ListDelegatingValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public ListIterator listIterator() { + public ListIterator<E> listIterator() { return listIterator(0); } - public ListIterator listIterator(final int index) { + public ListIterator<E> listIterator(final int index) { getterCalled(); - return new ListIterator() { - ListIterator it = masterList.listIterator(index); - Object lastMasterElement; - Object lastElement; + return new ListIterator<E>() { + ListIterator<T> it = masterList.listIterator(index); + T lastMasterElement; + E lastElement; boolean haveIterated = false; public void add(Object arg0) { @@ -238,7 +244,7 @@ public class ListDelegatingValueObservableList extends AbstractObservableList return it.hasPrevious(); } - public Object next() { + public E next() { getterCalled(); lastMasterElement = it.next(); lastElement = cache.get(lastMasterElement); @@ -251,7 +257,7 @@ public class ListDelegatingValueObservableList extends AbstractObservableList return it.nextIndex(); } - public Object previous() { + public E previous() { getterCalled(); lastMasterElement = it.previous(); lastElement = cache.get(lastMasterElement); @@ -268,7 +274,7 @@ public class ListDelegatingValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public void set(Object o) { + public void set(E o) { checkRealm(); if (!haveIterated) throw new IllegalStateException(); @@ -281,39 +287,38 @@ public class ListDelegatingValueObservableList extends AbstractObservableList } private int[] indicesOf(Object masterElement) { - List indices = new ArrayList(); + List<Integer> indices = new ArrayList<Integer>(); - for (ListIterator it = masterList.listIterator(); it.hasNext();) { + for (ListIterator<T> it = masterList.listIterator(); it.hasNext();) { if (masterElement == it.next()) indices.add(new Integer(it.previousIndex())); } int[] result = new int[indices.size()]; for (int i = 0; i < result.length; i++) { - result[i] = ((Integer) indices.get(i)).intValue(); + result[i] = indices.get(i).intValue(); } return result; } - private void fireListChange(int[] indices, Object oldValue, Object newValue) { - ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2]; + private void fireListChange(int[] indices, E oldValue, E newValue) { + List<ListDiffEntry<E>> differences = new ArrayList<ListDiffEntry<E>>( + indices.length * 2); for (int i = 0; i < indices.length; i++) { int index = indices[i]; - differences[i * 2] = Diffs.createListDiffEntry(index, false, - oldValue); - differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true, - newValue); + differences.add(Diffs.createListDiffEntry(index, false, oldValue)); + differences.add(Diffs.createListDiffEntry(index, true, newValue)); } fireListChange(Diffs.createListDiff(differences)); } - public Object remove(int index) { + public E remove(int index) { throw new UnsupportedOperationException(); } - public Object set(int index, Object o) { + public E set(int index, E o) { checkRealm(); - Object masterElement = masterList.get(index); + T masterElement = masterList.get(index); return cache.put(masterElement, o); } @@ -321,7 +326,7 @@ public class ListDelegatingValueObservableList extends AbstractObservableList return masterList; } - public IProperty getProperty() { + public DelegatingValueProperty<S, E> getProperty() { return detailProperty; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java index 54a08218..6f55fce6 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ListSimpleValueObservableList.java @@ -34,8 +34,8 @@ 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.value.ValueDiff; 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; @@ -46,21 +46,29 @@ import org.eclipse.core.internal.databinding.identity.IdentitySet; import org.eclipse.core.internal.databinding.property.Util; /** + * @param <S> + * type of the source object + * @param <M> + * type of the elements in the master list + * @param <T> + * type of the elements in the list, being the type of the value of + * the detail property * @since 1.2 */ -public class ListSimpleValueObservableList extends AbstractObservableList - implements IPropertyObservable { - private IObservableList masterList; - private SimpleValueProperty detailProperty; +public class ListSimpleValueObservableList<S, M extends S, T> extends + AbstractObservableList<T> implements + IPropertyObservable<SimpleValueProperty<S, T>> { + private IObservableList<M> masterList; + private SimpleValueProperty<S, T> detailProperty; - private IObservableSet knownMasterElements; - private Map cachedValues; - private Set staleElements; + private IObservableSet<M> knownMasterElements; + private Map<M, T> cachedValues; + private Set<M> staleElements; private boolean updating; - private IListChangeListener masterListener = new IListChangeListener() { - public void handleListChange(ListChangeEvent event) { + private IListChangeListener<M> masterListener = new IListChangeListener<M>() { + public void handleListChange(ListChangeEvent<M> event) { if (!isDisposed()) { updateKnownElements(); fireListChange(convertDiff(event.diff)); @@ -68,24 +76,23 @@ public class ListSimpleValueObservableList extends AbstractObservableList } private void updateKnownElements() { - Set identityKnownElements = new IdentitySet(masterList); + Set<M> identityKnownElements = new IdentitySet<M>(masterList); knownMasterElements.retainAll(identityKnownElements); knownMasterElements.addAll(identityKnownElements); } - private ListDiff convertDiff(ListDiff diff) { + private ListDiff<T> convertDiff(ListDiff<M> diff) { // Convert diff to detail value - ListDiffEntry[] masterEntries = diff.getDifferences(); - ListDiffEntry[] detailEntries = new ListDiffEntry[masterEntries.length]; - for (int i = 0; i < masterEntries.length; i++) { - ListDiffEntry masterDifference = masterEntries[i]; + List<ListDiffEntry<M>> masterEntries = diff.getDifferencesAsList(); + List<ListDiffEntry<T>> detailEntries = new ArrayList<ListDiffEntry<T>>( + masterEntries.size()); + for (ListDiffEntry<M> masterDifference : masterEntries) { int index = masterDifference.getPosition(); boolean addition = masterDifference.isAddition(); - Object masterElement = masterDifference.getElement(); - Object elementDetailValue = detailProperty - .getValue(masterElement); - detailEntries[i] = Diffs.createListDiffEntry(index, addition, - elementDetailValue); + M masterElement = masterDifference.getElement(); + T elementDetailValue = detailProperty.getValue(masterElement); + detailEntries.add(Diffs.createListDiffEntry(index, addition, + elementDetailValue)); } return Diffs.createListDiff(detailEntries); } @@ -97,28 +104,31 @@ public class ListSimpleValueObservableList extends AbstractObservableList } }; - private INativePropertyListener detailListener; + private INativePropertyListener<S> detailListener; /** * @param masterList * @param valueProperty */ - public ListSimpleValueObservableList(IObservableList masterList, - SimpleValueProperty valueProperty) { + public ListSimpleValueObservableList(IObservableList<M> masterList, + SimpleValueProperty<S, T> valueProperty) { super(masterList.getRealm()); this.masterList = masterList; this.detailProperty = valueProperty; - ISimplePropertyListener listener = new ISimplePropertyListener() { - public void handleEvent(final SimplePropertyEvent event) { + ISimplePropertyListener<ValueDiff<T>> listener = new ISimplePropertyListener<ValueDiff<T>>() { + public void handleEvent( + final SimplePropertyEvent<ValueDiff<T>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { + @SuppressWarnings("unchecked") + M source = (M) event.getSource(); if (event.type == SimplePropertyEvent.CHANGE) { - notifyIfChanged(event.getSource()); + notifyIfChanged(source); } else if (event.type == SimplePropertyEvent.STALE) { boolean wasStale = !staleElements.isEmpty(); - staleElements.add(event.getSource()); + staleElements.add(source); if (!wasStale) fireStale(); } @@ -133,26 +143,26 @@ public class ListSimpleValueObservableList extends AbstractObservableList protected void firstListenerAdded() { ObservableTracker.setIgnore(true); try { - knownMasterElements = new IdentityObservableSet(getRealm(), null); + knownMasterElements = new IdentityObservableSet<M>(getRealm(), null); } finally { ObservableTracker.setIgnore(false); } - cachedValues = new IdentityMap(); - staleElements = new IdentitySet(); - knownMasterElements.addSetChangeListener(new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { - for (Iterator it = event.diff.getRemovals().iterator(); it + cachedValues = new IdentityMap<M, T>(); + staleElements = new IdentitySet<M>(); + knownMasterElements.addSetChangeListener(new ISetChangeListener<M>() { + public void handleSetChange(SetChangeEvent<M> event) { + for (Iterator<M> it = event.diff.getRemovals().iterator(); it .hasNext();) { - Object key = it.next(); + M key = it.next(); if (detailListener != null) detailListener.removeFrom(key); cachedValues.remove(key); staleElements.remove(key); } - for (Iterator it = event.diff.getAdditions().iterator(); it + for (Iterator<M> it = event.diff.getAdditions().iterator(); it .hasNext();) { - Object key = it.next(); + M key = it.next(); cachedValues.put(key, detailProperty.getValue(key)); if (detailListener != null) detailListener.addTo(key); @@ -201,9 +211,9 @@ public class ListSimpleValueObservableList extends AbstractObservableList return detailProperty.getValueType(); } - public Object get(int index) { + public T get(int index) { getterCalled(); - Object masterElement = masterList.get(index); + M masterElement = masterList.get(index); return detailProperty.getValue(masterElement); } @@ -211,18 +221,18 @@ public class ListSimpleValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public boolean addAll(Collection c) { + public boolean addAll(Collection<? extends T> c) { throw new UnsupportedOperationException(); } - public boolean addAll(int index, Collection c) { + public boolean addAll(int index, Collection<? extends T> c) { throw new UnsupportedOperationException(); } public boolean contains(Object o) { getterCalled(); - for (Iterator it = masterList.iterator(); it.hasNext();) { + for (Iterator<M> it = masterList.iterator(); it.hasNext();) { if (Util.equals(detailProperty.getValue(it.next()), o)) return true; } @@ -240,19 +250,19 @@ public class ListSimpleValueObservableList extends AbstractObservableList && !staleElements.isEmpty(); } - public Iterator iterator() { + public Iterator<T> iterator() { getterCalled(); - return new Iterator() { - Iterator it = masterList.iterator(); + return new Iterator<T>() { + Iterator<M> it = masterList.iterator(); public boolean hasNext() { getterCalled(); return it.hasNext(); } - public Object next() { + public T next() { getterCalled(); - Object masterElement = it.next(); + M masterElement = it.next(); return detailProperty.getValue(masterElement); } @@ -262,7 +272,7 @@ public class ListSimpleValueObservableList extends AbstractObservableList }; } - public Object move(int oldIndex, int newIndex) { + public T move(int oldIndex, int newIndex) { throw new UnsupportedOperationException(); } @@ -270,32 +280,35 @@ public class ListSimpleValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public boolean removeAll(Collection c) { + public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } - public boolean retainAll(Collection c) { + public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } + @SuppressWarnings("unchecked") public Object[] toArray() { getterCalled(); Object[] masterElements = masterList.toArray(); Object[] result = new Object[masterElements.length]; for (int i = 0; i < result.length; i++) { - result[i] = detailProperty.getValue(masterElements[i]); + // cast is always safe as we get the array from a list of Us + result[i] = detailProperty.getValue((M) masterElements[i]); } return result; } - public Object[] toArray(Object[] a) { + @SuppressWarnings("unchecked") + public <V> V[] toArray(V[] a) { getterCalled(); Object[] masterElements = masterList.toArray(); if (a.length < masterElements.length) - a = (Object[]) Array.newInstance(a.getClass().getComponentType(), + a = (V[]) Array.newInstance(a.getClass().getComponentType(), masterElements.length); for (int i = 0; i < masterElements.length; i++) { - a[i] = detailProperty.getValue(masterElements[i]); + a[i] = (V) detailProperty.getValue((M) masterElements[i]); } return a; } @@ -308,16 +321,16 @@ public class ListSimpleValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public ListIterator listIterator() { + public ListIterator<T> listIterator() { return listIterator(0); } - public ListIterator listIterator(final int index) { + public ListIterator<T> listIterator(final int index) { getterCalled(); - return new ListIterator() { - ListIterator it = masterList.listIterator(index); - Object lastMasterElement; - Object lastElement; + return new ListIterator<T>() { + ListIterator<M> it = masterList.listIterator(index); + M lastMasterElement; + T lastElement; boolean haveIterated = false; public void add(Object arg0) { @@ -334,7 +347,7 @@ public class ListSimpleValueObservableList extends AbstractObservableList return it.hasPrevious(); } - public Object next() { + public T next() { getterCalled(); lastMasterElement = it.next(); lastElement = detailProperty.getValue(lastMasterElement); @@ -347,7 +360,7 @@ public class ListSimpleValueObservableList extends AbstractObservableList return it.nextIndex(); } - public Object previous() { + public T previous() { getterCalled(); lastMasterElement = it.previous(); lastElement = detailProperty.getValue(lastMasterElement); @@ -364,7 +377,7 @@ public class ListSimpleValueObservableList extends AbstractObservableList throw new UnsupportedOperationException(); } - public void set(Object o) { + public void set(T o) { checkRealm(); if (!haveIterated) throw new IllegalStateException(); @@ -372,7 +385,8 @@ public class ListSimpleValueObservableList extends AbstractObservableList boolean wasUpdating = updating; updating = true; try { - detailProperty.setValue(lastElement, o); + // detailProperty.setValue(lastElement, o); // jpp: bug! + detailProperty.setValue(lastMasterElement, o); } finally { updating = wasUpdating; } @@ -384,10 +398,10 @@ public class ListSimpleValueObservableList extends AbstractObservableList }; } - private void notifyIfChanged(Object masterElement) { + private void notifyIfChanged(M masterElement) { if (cachedValues != null) { - Object oldValue = cachedValues.get(masterElement); - Object newValue = detailProperty.getValue(masterElement); + T oldValue = cachedValues.get(masterElement); + T newValue = detailProperty.getValue(masterElement); if (!Util.equals(oldValue, newValue) || staleElements.contains(masterElement)) { cachedValues.put(masterElement, newValue); @@ -398,9 +412,9 @@ public class ListSimpleValueObservableList extends AbstractObservableList } private int[] indicesOf(Object masterElement) { - List indices = new ArrayList(); + List<Integer> indices = new ArrayList<Integer>(); - for (ListIterator it = ListSimpleValueObservableList.this.masterList + for (ListIterator<M> it = ListSimpleValueObservableList.this.masterList .listIterator(); it.hasNext();) { if (masterElement == it.next()) indices.add(new Integer(it.previousIndex())); @@ -408,31 +422,29 @@ public class ListSimpleValueObservableList extends AbstractObservableList int[] result = new int[indices.size()]; for (int i = 0; i < result.length; i++) { - result[i] = ((Integer) indices.get(i)).intValue(); + result[i] = indices.get(i).intValue(); } return result; } - private void fireListChange(int[] indices, Object oldValue, Object newValue) { - ListDiffEntry[] differences = new ListDiffEntry[indices.length * 2]; - for (int i = 0; i < indices.length; i++) { - int index = indices[i]; - differences[i * 2] = Diffs.createListDiffEntry(index, false, - oldValue); - differences[i * 2 + 1] = Diffs.createListDiffEntry(index, true, - newValue); + private void fireListChange(int[] indices, T oldValue, T newValue) { + List<ListDiffEntry<T>> differences = new ArrayList<ListDiffEntry<T>>( + indices.length * 2); + for (int index : indices) { + differences.add(Diffs.createListDiffEntry(index, false, oldValue)); + differences.add(Diffs.createListDiffEntry(index, true, newValue)); } fireListChange(Diffs.createListDiff(differences)); } - public Object remove(int index) { + public T remove(int index) { throw new UnsupportedOperationException(); } - public Object set(int index, Object o) { + public T set(int index, T o) { checkRealm(); - Object masterElement = masterList.get(index); - Object oldValue = detailProperty.getValue(masterElement); + M masterElement = masterList.get(index); + T oldValue = detailProperty.getValue(masterElement); boolean wasUpdating = updating; updating = true; @@ -451,7 +463,7 @@ public class ListSimpleValueObservableList extends AbstractObservableList return masterList; } - public IProperty getProperty() { + public SimpleValueProperty<S, T> getProperty() { return detailProperty; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapDelegatingValueObservableMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapDelegatingValueObservableMap.java index feb2d383..f5d04685 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapDelegatingValueObservableMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapDelegatingValueObservableMap.java @@ -28,35 +28,43 @@ 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.property.IProperty; import org.eclipse.core.databinding.property.IPropertyObservable; import org.eclipse.core.databinding.property.value.DelegatingValueProperty; import org.eclipse.core.internal.databinding.property.Util; /** + * @param <S> + * type of the source object + * @param <I> + * type of the intermediate values + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 */ -public class MapDelegatingValueObservableMap extends AbstractObservableMap - implements IPropertyObservable { - private IObservableMap masterMap; - private DelegatingValueProperty detailProperty; - private DelegatingCache cache; +public class MapDelegatingValueObservableMap<S, K, I extends S, V> extends + AbstractObservableMap<K, V> implements + IPropertyObservable<DelegatingValueProperty<S, V>> { + private IObservableMap<K, I> masterMap; + private DelegatingValueProperty<S, V> detailProperty; + private DelegatingCache<S, I, V> cache; - private Set entrySet; + private Set<Map.Entry<K, V>> entrySet; - class EntrySet extends AbstractSet { - public Iterator iterator() { - return new Iterator() { - Iterator it = masterMap.entrySet().iterator(); + class EntrySet extends AbstractSet<Map.Entry<K, V>> { + public Iterator<Map.Entry<K, V>> iterator() { + return new Iterator<Map.Entry<K, V>>() { + Iterator<Map.Entry<K, I>> it = masterMap.entrySet().iterator(); public boolean hasNext() { getterCalled(); return it.hasNext(); } - public Object next() { + public Map.Entry<K, V> next() { getterCalled(); - Map.Entry next = (Map.Entry) it.next(); + Map.Entry<K, I> next = it.next(); return new MapEntry(next.getKey()); } @@ -71,35 +79,35 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap } } - class MapEntry implements Map.Entry { - private Object key; + class MapEntry implements Map.Entry<K, V> { + private K key; - MapEntry(Object key) { + MapEntry(K key) { this.key = key; } - public Object getKey() { + public K getKey() { getterCalled(); return key; } - public Object getValue() { + public V getValue() { getterCalled(); if (!masterMap.containsKey(key)) return null; - Object masterValue = masterMap.get(key); + I masterValue = masterMap.get(key); return cache.get(masterValue); } - public Object setValue(Object value) { + public V setValue(V value) { checkRealm(); if (!masterMap.containsKey(key)) return null; - Object masterValue = masterMap.get(key); + I masterValue = masterMap.get(key); return cache.put(masterValue, value); } @@ -111,7 +119,7 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap return false; if (!(o instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) o; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) o; return Util.equals(this.getKey(), that.getKey()) && Util.equals(this.getValue(), that.getValue()); } @@ -124,50 +132,50 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap } } - private IMapChangeListener masterListener = new IMapChangeListener() { - public void handleMapChange(final MapChangeEvent event) { + private IMapChangeListener<K, I> masterListener = new IMapChangeListener<K, I>() { + public void handleMapChange(final MapChangeEvent<K, I> event) { if (isDisposed()) return; cache.addAll(masterMap.values()); // Need both obsolete and new master values to convert diff - MapDiff diff = convertDiff(event.diff); + MapDiff<K, V> diff = convertDiff(event.diff); cache.retainAll(masterMap.values()); fireMapChange(diff); } - private MapDiff convertDiff(MapDiff diff) { - Map oldValues = new HashMap(); - Map newValues = new HashMap(); + private MapDiff<K, V> convertDiff(MapDiff<K, I> diff) { + Map<K, V> oldValues = new HashMap<K, V>(); + Map<K, V> newValues = new HashMap<K, V>(); - Set addedKeys = diff.getAddedKeys(); - for (Iterator it = addedKeys.iterator(); it.hasNext();) { - Object key = it.next(); - Object masterValue = diff.getNewValue(key); - Object newValue = cache.get(masterValue); + Set<K> addedKeys = diff.getAddedKeys(); + for (Iterator<K> it = addedKeys.iterator(); it.hasNext();) { + K key = it.next(); + I masterValue = diff.getNewValue(key); + V newValue = cache.get(masterValue); newValues.put(key, newValue); } - Set removedKeys = diff.getRemovedKeys(); - for (Iterator it = removedKeys.iterator(); it.hasNext();) { - Object key = it.next(); - Object masterValue = diff.getOldValue(key); - Object oldValue = cache.get(masterValue); + Set<K> removedKeys = diff.getRemovedKeys(); + for (Iterator<K> it = removedKeys.iterator(); it.hasNext();) { + K key = it.next(); + I masterValue = diff.getOldValue(key); + V oldValue = cache.get(masterValue); oldValues.put(key, oldValue); } - Set changedKeys = new HashSet(diff.getChangedKeys()); - for (Iterator it = changedKeys.iterator(); it.hasNext();) { - Object key = it.next(); + Set<K> changedKeys = new HashSet<K>(diff.getChangedKeys()); + for (Iterator<K> it = changedKeys.iterator(); it.hasNext();) { + K key = it.next(); - Object oldMasterValue = diff.getOldValue(key); - Object newMasterValue = diff.getNewValue(key); + I oldMasterValue = diff.getOldValue(key); + I newMasterValue = diff.getNewValue(key); - Object oldValue = cache.get(oldMasterValue); - Object newValue = cache.get(newMasterValue); + V oldValue = cache.get(oldMasterValue); + V newValue = cache.get(newMasterValue); if (Util.equals(oldValue, newValue)) { it.remove(); @@ -192,14 +200,13 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap * @param map * @param valueProperty */ - public MapDelegatingValueObservableMap(IObservableMap map, - DelegatingValueProperty valueProperty) { + public MapDelegatingValueObservableMap(IObservableMap<K, I> map, + DelegatingValueProperty<S, V> valueProperty) { super(map.getRealm()); this.masterMap = map; this.detailProperty = valueProperty; - this.cache = new DelegatingCache(getRealm(), valueProperty) { - void handleValueChange(Object masterElement, Object oldValue, - Object newValue) { + this.cache = new DelegatingCache<S, I, V>(getRealm(), valueProperty) { + void handleValueChange(I masterElement, V oldValue, V newValue) { fireMapChange(keysFor(masterElement), oldValue, newValue); } }; @@ -209,7 +216,7 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap masterMap.addStaleListener(staleListener); } - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { getterCalled(); if (entrySet == null) entrySet = new EntrySet(); @@ -220,16 +227,16 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap ObservableTracker.getterCalled(this); } - public Object get(Object key) { + public V get(Object key) { getterCalled(); Object masterValue = masterMap.get(key); return cache.get(masterValue); } - public Object put(Object key, Object value) { + public V put(K key, V value) { if (!masterMap.containsKey(key)) return null; - Object masterValue = masterMap.get(key); + I masterValue = masterMap.get(key); return cache.put(masterValue, value); } @@ -242,7 +249,7 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap return masterMap; } - public IProperty getProperty() { + public DelegatingValueProperty<S, V> getProperty() { return detailProperty; } @@ -254,11 +261,10 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap return detailProperty.getValueType(); } - private Set keysFor(Object masterValue) { - Set keys = new HashSet(); + private Set<K> keysFor(I masterValue) { + Set<K> keys = new HashSet<K>(); - for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Entry) it.next(); + for (Map.Entry<K, I> entry : masterMap.entrySet()) { if (entry.getValue() == masterValue) { keys.add(entry.getKey()); } @@ -267,28 +273,28 @@ public class MapDelegatingValueObservableMap extends AbstractObservableMap return keys; } - private void fireMapChange(final Set changedKeys, final Object oldValue, - final Object newValue) { - fireMapChange(new MapDiff() { - public Set getAddedKeys() { - return Collections.EMPTY_SET; + private void fireMapChange(final Set<K> changedKeys, final V oldValue, + final V newValue) { + fireMapChange(new MapDiff<K, V>() { + public Set<K> getAddedKeys() { + return Collections.emptySet(); } - public Set getRemovedKeys() { - return Collections.EMPTY_SET; + public Set<K> getRemovedKeys() { + return Collections.emptySet(); } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return Collections.unmodifiableSet(changedKeys); } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { if (changedKeys.contains(key)) return oldValue; return null; } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { if (changedKeys.contains(key)) return newValue; return null; diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java index d6e24f23..04ef4968 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/MapSimpleValueObservableMap.java @@ -31,8 +31,8 @@ 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.value.ValueDiff; 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; @@ -43,22 +43,31 @@ import org.eclipse.core.internal.databinding.identity.IdentitySet; import org.eclipse.core.internal.databinding.property.Util; /** + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <I> + * type of the intermediate values + * @param <V> + * type of the values in the map * @since 1.2 * */ -public class MapSimpleValueObservableMap extends AbstractObservableMap - implements IPropertyObservable { - private IObservableMap masterMap; - private SimpleValueProperty detailProperty; +public class MapSimpleValueObservableMap<S, K, I extends S, V> extends + AbstractObservableMap<K, V> implements + IPropertyObservable<SimpleValueProperty<S, V>> { + private IObservableMap<K, I> masterMap; + private SimpleValueProperty<S, V> detailProperty; - private IObservableSet knownMasterValues; - private Map cachedValues; - private Set staleMasterValues; + private IObservableSet<I> knownMasterValues; + private Map<I, V> cachedValues; + private Set<I> staleMasterValues; private boolean updating = false; - private IMapChangeListener masterListener = new IMapChangeListener() { - public void handleMapChange(final MapChangeEvent event) { + private IMapChangeListener<K, I> masterListener = new IMapChangeListener<K, I>() { + public void handleMapChange(final MapChangeEvent<K, I> event) { if (!isDisposed()) { updateKnownValues(); if (!updating) @@ -67,40 +76,40 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap } private void updateKnownValues() { - Set knownValues = new IdentitySet(masterMap.values()); + Set<I> knownValues = new IdentitySet<I>(masterMap.values()); knownMasterValues.retainAll(knownValues); knownMasterValues.addAll(knownValues); } - private MapDiff convertDiff(MapDiff diff) { - Map oldValues = new IdentityMap(); - Map newValues = new IdentityMap(); + private MapDiff<K, V> convertDiff(MapDiff<K, I> diff) { + Map<K, V> oldValues = new IdentityMap<K, V>(); + Map<K, V> newValues = new IdentityMap<K, V>(); - Set addedKeys = diff.getAddedKeys(); - for (Iterator it = addedKeys.iterator(); it.hasNext();) { - Object key = it.next(); - Object newSource = diff.getNewValue(key); - Object newValue = detailProperty.getValue(newSource); + Set<K> addedKeys = diff.getAddedKeys(); + for (Iterator<K> it = addedKeys.iterator(); it.hasNext();) { + K key = it.next(); + I newSource = diff.getNewValue(key); + V newValue = detailProperty.getValue(newSource); newValues.put(key, newValue); } - Set removedKeys = diff.getRemovedKeys(); - for (Iterator it = removedKeys.iterator(); it.hasNext();) { - Object key = it.next(); - Object oldSource = diff.getOldValue(key); - Object oldValue = detailProperty.getValue(oldSource); + Set<K> removedKeys = diff.getRemovedKeys(); + for (Iterator<K> it = removedKeys.iterator(); it.hasNext();) { + K key = it.next(); + I oldSource = diff.getOldValue(key); + V oldValue = detailProperty.getValue(oldSource); oldValues.put(key, oldValue); } - Set changedKeys = new IdentitySet(diff.getChangedKeys()); - for (Iterator it = changedKeys.iterator(); it.hasNext();) { - Object key = it.next(); + Set<K> changedKeys = new IdentitySet<K>(diff.getChangedKeys()); + for (Iterator<K> it = changedKeys.iterator(); it.hasNext();) { + K key = it.next(); - Object oldSource = diff.getOldValue(key); - Object newSource = diff.getNewValue(key); + I oldSource = diff.getOldValue(key); + I newSource = diff.getNewValue(key); - Object oldValue = detailProperty.getValue(oldSource); - Object newValue = detailProperty.getValue(newSource); + V oldValue = detailProperty.getValue(oldSource); + V newValue = detailProperty.getValue(newSource); if (Util.equals(oldValue, newValue)) { it.remove(); @@ -121,28 +130,32 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap } }; - private INativePropertyListener detailListener; + private INativePropertyListener<S> detailListener; /** * @param map * @param valueProperty */ - public MapSimpleValueObservableMap(IObservableMap map, - SimpleValueProperty valueProperty) { + public MapSimpleValueObservableMap(IObservableMap<K, I> map, + SimpleValueProperty<S, V> valueProperty) { super(map.getRealm()); this.masterMap = map; this.detailProperty = valueProperty; - ISimplePropertyListener listener = new ISimplePropertyListener() { - public void handleEvent(final SimplePropertyEvent event) { + ISimplePropertyListener<ValueDiff<V>> listener = new ISimplePropertyListener<ValueDiff<V>>() { + public void handleEvent( + final SimplePropertyEvent<ValueDiff<V>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { + // TODO should we type the source, too? + @SuppressWarnings("unchecked") + I source = (I) event.getSource(); if (event.type == SimplePropertyEvent.CHANGE) { - notifyIfChanged(event.getSource()); + notifyIfChanged(source); } else if (event.type == SimplePropertyEvent.STALE) { boolean wasStale = !staleMasterValues.isEmpty(); - staleMasterValues.add(event.getSource()); + staleMasterValues.add(source); if (!wasStale) fireStale(); } @@ -165,26 +178,26 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap protected void firstListenerAdded() { ObservableTracker.setIgnore(true); try { - knownMasterValues = new IdentityObservableSet(getRealm(), null); + knownMasterValues = new IdentityObservableSet<I>(getRealm(), null); } finally { ObservableTracker.setIgnore(false); } - cachedValues = new IdentityMap(); - staleMasterValues = new IdentitySet(); - knownMasterValues.addSetChangeListener(new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { - for (Iterator it = event.diff.getRemovals().iterator(); it + cachedValues = new IdentityMap<I, V>(); + staleMasterValues = new IdentitySet<I>(); + knownMasterValues.addSetChangeListener(new ISetChangeListener<I>() { + public void handleSetChange(SetChangeEvent<I> event) { + for (Iterator<I> it = event.diff.getRemovals().iterator(); it .hasNext();) { - Object key = it.next(); + I key = it.next(); if (detailListener != null) detailListener.removeFrom(key); cachedValues.remove(key); staleMasterValues.remove(key); } - for (Iterator it = event.diff.getAdditions().iterator(); it + for (Iterator<I> it = event.diff.getAdditions().iterator(); it .hasNext();) { - Object key = it.next(); + I key = it.next(); cachedValues.put(key, detailProperty.getValue(key)); if (detailListener != null) detailListener.addTo(key); @@ -215,28 +228,28 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap staleMasterValues = null; } - private Set entrySet; + private Set<Map.Entry<K, V>> entrySet; - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { getterCalled(); if (entrySet == null) entrySet = new EntrySet(); return entrySet; } - class EntrySet extends AbstractSet { - public Iterator iterator() { - return new Iterator() { - Iterator it = masterMap.entrySet().iterator(); + class EntrySet extends AbstractSet<Map.Entry<K, V>> { + public Iterator<Map.Entry<K, V>> iterator() { + return new Iterator<Map.Entry<K, V>>() { + Iterator<Map.Entry<K, I>> it = masterMap.entrySet().iterator(); public boolean hasNext() { getterCalled(); return it.hasNext(); } - public Object next() { + public Map.Entry<K, V> next() { getterCalled(); - Map.Entry next = (Map.Entry) it.next(); + Map.Entry<K, I> next = it.next(); return new MapEntry(next.getKey()); } @@ -251,31 +264,31 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap } } - class MapEntry implements Map.Entry { - private Object key; + class MapEntry implements Map.Entry<K, V> { + private K key; - MapEntry(Object key) { + MapEntry(K key) { this.key = key; } - public Object getKey() { + public K getKey() { getterCalled(); return key; } - public Object getValue() { + public V getValue() { getterCalled(); if (!masterMap.containsKey(key)) return null; return detailProperty.getValue(masterMap.get(key)); } - public Object setValue(Object value) { + public V setValue(V value) { if (!masterMap.containsKey(key)) return null; - Object source = masterMap.get(key); + I source = masterMap.get(key); - Object oldValue = detailProperty.getValue(source); + V oldValue = detailProperty.getValue(source); updating = true; try { @@ -297,7 +310,7 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap return false; if (!(o instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) o; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) o; return Util.equals(this.getKey(), that.getKey()) && Util.equals(this.getValue(), that.getValue()); } @@ -316,62 +329,62 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap return masterMap.containsKey(key); } - public Object get(Object key) { + public V get(Object key) { getterCalled(); return detailProperty.getValue(masterMap.get(key)); } - public Object put(Object key, Object value) { + public V put(K key, V value) { if (!masterMap.containsKey(key)) return null; - Object masterValue = masterMap.get(key); - Object oldValue = detailProperty.getValue(masterValue); + I masterValue = masterMap.get(key); + V oldValue = detailProperty.getValue(masterValue); detailProperty.setValue(masterValue, value); notifyIfChanged(masterValue); return oldValue; } - public Object remove(Object key) { + public V remove(Object key) { checkRealm(); - Object masterValue = masterMap.get(key); - Object oldValue = detailProperty.getValue(masterValue); + I masterValue = masterMap.get(key); + V oldValue = detailProperty.getValue(masterValue); masterMap.remove(key); return oldValue; } - private void notifyIfChanged(Object masterValue) { + private void notifyIfChanged(I masterValue) { if (cachedValues != null) { - final Set keys = keysFor(masterValue); + final Set<K> keys = keysFor(masterValue); - final Object oldValue = cachedValues.get(masterValue); - final Object newValue = detailProperty.getValue(masterValue); + final V oldValue = cachedValues.get(masterValue); + final V newValue = detailProperty.getValue(masterValue); if (!Util.equals(oldValue, newValue) || staleMasterValues.contains(masterValue)) { cachedValues.put(masterValue, newValue); staleMasterValues.remove(masterValue); - fireMapChange(new MapDiff() { - public Set getAddedKeys() { - return Collections.EMPTY_SET; + fireMapChange(new MapDiff<K, V>() { + public Set<K> getAddedKeys() { + return Collections.emptySet(); } - public Set getChangedKeys() { + public Set<K> getChangedKeys() { return keys; } - public Set getRemovedKeys() { - return Collections.EMPTY_SET; + public Set<K> getRemovedKeys() { + return Collections.emptySet(); } - public Object getNewValue(Object key) { + public V getNewValue(Object key) { return newValue; } - public Object getOldValue(Object key) { + public V getOldValue(Object key) { return oldValue; } }); @@ -379,11 +392,10 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap } } - private Set keysFor(Object value) { - Set keys = new IdentitySet(); + private Set<K> keysFor(I value) { + Set<K> keys = new IdentitySet<K>(); - for (Iterator it = masterMap.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Entry) it.next(); + for (Map.Entry<K, I> entry : masterMap.entrySet()) { if (entry.getValue() == value) { keys.add(entry.getKey()); } @@ -406,7 +418,7 @@ public class MapSimpleValueObservableMap extends AbstractObservableMap return masterMap; } - public IProperty getProperty() { + public SimpleValueProperty<S, V> getProperty() { return detailProperty; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ObservableValueProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ObservableValueProperty.java index fc619fd6..eb203e11 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ObservableValueProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/ObservableValueProperty.java @@ -18,6 +18,7 @@ import org.eclipse.core.databinding.observable.StaleEvent; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; +import org.eclipse.core.databinding.observable.value.ValueDiff; import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.IProperty; import org.eclipse.core.databinding.property.ISimplePropertyListener; @@ -25,6 +26,8 @@ import org.eclipse.core.databinding.property.NativePropertyListener; import org.eclipse.core.databinding.property.value.SimpleValueProperty; /** + * @param <T> + * type of the value of the property * @since 3.3 * */ @@ -35,7 +38,8 @@ import org.eclipse.core.databinding.property.value.SimpleValueProperty; * observeDetail(IObservableValue) we just cast the source object to * IObservableValue and return it. */ -public class ObservableValueProperty extends SimpleValueProperty { +public class ObservableValueProperty<T> extends + SimpleValueProperty<IObservableValue<T>, T> { private final Object valueType; /** @@ -49,49 +53,51 @@ public class ObservableValueProperty extends SimpleValueProperty { return valueType; } - protected Object doGetValue(Object source) { - return ((IObservableValue) source).getValue(); + protected T doGetValue(IObservableValue<T> source) { + return source.getValue(); } - protected void doSetValue(Object source, Object value) { - ((IObservableValue) source).setValue(value); + protected void doSetValue(IObservableValue<T> source, T value) { + source.setValue(value); } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<IObservableValue<T>> adaptListener( + ISimplePropertyListener<ValueDiff<T>> listener) { return new Listener(this, listener); } - private class Listener extends NativePropertyListener implements - IValueChangeListener, IStaleListener { - Listener(IProperty property, ISimplePropertyListener listener) { + private class Listener extends + NativePropertyListener<IObservableValue<T>, ValueDiff<T>> implements + IValueChangeListener<T>, IStaleListener { + Listener(IProperty property, + ISimplePropertyListener<ValueDiff<T>> listener) { super(property, listener); } - public void handleValueChange(ValueChangeEvent event) { - fireChange(event.getObservable(), event.diff); + public void handleValueChange(ValueChangeEvent<T> event) { + fireChange(event.getObservableValue(), event.diff); } public void handleStale(StaleEvent event) { fireStale(event.getObservable()); } - protected void doAddTo(Object source) { - IObservableValue observable = (IObservableValue) source; + protected void doAddTo(IObservableValue<T> source) { + IObservableValue<T> observable = source; observable.addValueChangeListener(this); observable.addStaleListener(this); } - protected void doRemoveFrom(Object source) { - IObservableValue observable = (IObservableValue) source; + protected void doRemoveFrom(IObservableValue<T> source) { + IObservableValue<T> observable = source; observable.removeValueChangeListener(this); observable.removeStaleListener(this); } } - public IObservableValue observe(Realm realm, Object source) { + public IObservableValue<T> observe(Realm realm, IObservableValue<T> source) { // Ignore realm if different - return (IObservableValue) source; + return source; } public String toString() { diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SelfValueProperty.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SelfValueProperty.java index 95743acc..dc92b997 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SelfValueProperty.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SelfValueProperty.java @@ -11,15 +11,18 @@ package org.eclipse.core.internal.databinding.property.value; +import org.eclipse.core.databinding.observable.value.ValueDiff; import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.value.SimpleValueProperty; /** + * @param <T> + * type of the value of the property * @since 3.3 * */ -public final class SelfValueProperty extends SimpleValueProperty { +public final class SelfValueProperty<T> extends SimpleValueProperty<T, T> { private final Object valueType; /** @@ -33,22 +36,22 @@ public final class SelfValueProperty extends SimpleValueProperty { return valueType; } - protected Object doGetValue(Object source) { + protected T doGetValue(T source) { return source; } - protected void doSetValue(Object source, Object value) { + protected void doSetValue(T source, T value) { } - public INativePropertyListener adaptListener( - ISimplePropertyListener listener) { + public INativePropertyListener<T> adaptListener( + ISimplePropertyListener<ValueDiff<T>> listener) { return null; } - protected void doAddListener(Object source, INativePropertyListener listener) { + protected void doAddListener(T source, INativePropertyListener<T> listener) { } - protected void doRemoveListener(Object source, - INativePropertyListener listener) { + protected void doRemoveListener(T source, + INativePropertyListener<T> listener) { } }
\ No newline at end of file diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetDelegatingValueObservableMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetDelegatingValueObservableMap.java index d2f7ec22..1f1af244 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetDelegatingValueObservableMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetDelegatingValueObservableMap.java @@ -28,32 +28,38 @@ 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.SetDiff; -import org.eclipse.core.databinding.property.IProperty; import org.eclipse.core.databinding.property.IPropertyObservable; import org.eclipse.core.databinding.property.value.DelegatingValueProperty; import org.eclipse.core.internal.databinding.property.Util; /** + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 */ -public class SetDelegatingValueObservableMap extends AbstractObservableMap - implements IPropertyObservable { - private IObservableSet masterSet; - private DelegatingValueProperty detailProperty; - private DelegatingCache cache; +public class SetDelegatingValueObservableMap<S, K extends S, V> extends + AbstractObservableMap<K, V> implements + IPropertyObservable<DelegatingValueProperty<S, V>> { + private IObservableSet<K> masterSet; + private DelegatingValueProperty<S, V> detailProperty; + private DelegatingCache<S, K, V> cache; - private Set entrySet; + private Set<Map.Entry<K, V>> entrySet; - class EntrySet extends AbstractSet { - public Iterator iterator() { - return new Iterator() { - final Iterator it = masterSet.iterator(); + class EntrySet extends AbstractSet<Map.Entry<K, V>> { + public Iterator<Map.Entry<K, V>> iterator() { + return new Iterator<Map.Entry<K, V>>() { + final Iterator<K> it = masterSet.iterator(); public boolean hasNext() { return it.hasNext(); } - public Object next() { + public Map.Entry<K, V> next() { return new MapEntry(it.next()); } @@ -68,19 +74,19 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap } } - class MapEntry implements Map.Entry { - private final Object key; + class MapEntry implements Map.Entry<K, V> { + private final K key; - MapEntry(Object key) { + MapEntry(K key) { this.key = key; } - public Object getKey() { + public K getKey() { getterCalled(); return key; } - public Object getValue() { + public V getValue() { getterCalled(); if (!masterSet.contains(key)) @@ -89,7 +95,7 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap return cache.get(key); } - public Object setValue(Object value) { + public V setValue(V value) { checkRealm(); if (!masterSet.contains(key)) @@ -106,7 +112,7 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap return false; if (!(o instanceof Map.Entry)) return false; - Map.Entry that = (Map.Entry) o; + Map.Entry<?, ?> that = (Map.Entry<?, ?>) o; return Util.equals(this.getKey(), that.getKey()) && Util.equals(this.getValue(), that.getValue()); } @@ -119,36 +125,36 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap } } - private ISetChangeListener masterListener = new ISetChangeListener() { - public void handleSetChange(SetChangeEvent event) { + private ISetChangeListener<K> masterListener = new ISetChangeListener<K>() { + public void handleSetChange(SetChangeEvent<K> event) { if (isDisposed()) return; cache.addAll(masterSet); // Need both obsolete and new elements to convert diff - MapDiff diff = convertDiff(event.diff); + MapDiff<K, V> diff = convertDiff(event.diff); cache.retainAll(masterSet); fireMapChange(diff); } - private MapDiff convertDiff(SetDiff diff) { + private MapDiff<K, V> convertDiff(SetDiff<K> diff) { // Convert diff to detail value - Map oldValues = new HashMap(); - Map newValues = new HashMap(); + Map<K, V> oldValues = new HashMap<K, V>(); + Map<K, V> newValues = new HashMap<K, V>(); - for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) { - Object masterElement = it.next(); + for (Iterator<K> it = diff.getRemovals().iterator(); it.hasNext();) { + K masterElement = it.next(); oldValues.put(masterElement, cache.get(masterElement)); } - for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) { - Object masterElement = it.next(); + for (Iterator<K> it = diff.getAdditions().iterator(); it.hasNext();) { + K masterElement = it.next(); newValues.put(masterElement, cache.get(masterElement)); } return Diffs.createMapDiff(diff.getAdditions(), diff.getRemovals(), - Collections.EMPTY_SET, oldValues, newValues); + Collections.<K> emptySet(), oldValues, newValues); } }; @@ -162,14 +168,13 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap * @param keySet * @param valueProperty */ - public SetDelegatingValueObservableMap(IObservableSet keySet, - DelegatingValueProperty valueProperty) { + public SetDelegatingValueObservableMap(IObservableSet<K> keySet, + DelegatingValueProperty<S, V> valueProperty) { super(keySet.getRealm()); this.masterSet = keySet; this.detailProperty = valueProperty; - this.cache = new DelegatingCache(getRealm(), valueProperty) { - void handleValueChange(Object masterElement, Object oldValue, - Object newValue) { + this.cache = new DelegatingCache<S, K, V>(getRealm(), valueProperty) { + void handleValueChange(K masterElement, V oldValue, V newValue) { fireMapChange(Diffs.createMapDiffSingleChange(masterElement, oldValue, newValue)); } @@ -180,7 +185,7 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap masterSet.addStaleListener(staleListener); } - public Set entrySet() { + public Set<Map.Entry<K, V>> entrySet() { getterCalled(); if (entrySet == null) entrySet = new EntrySet(); @@ -191,12 +196,12 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap ObservableTracker.getterCalled(this); } - public Object get(Object key) { + public V get(Object key) { getterCalled(); return cache.get(key); } - public Object put(Object key, Object value) { + public V put(K key, V value) { checkRealm(); return cache.put(key, value); } @@ -209,7 +214,7 @@ public class SetDelegatingValueObservableMap extends AbstractObservableMap return masterSet; } - public IProperty getProperty() { + public DelegatingValueProperty<S, V> getProperty() { return detailProperty; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java index 26a57657..12bb029f 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SetSimpleValueObservableMap.java @@ -19,8 +19,8 @@ import java.util.Set; 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.observable.value.ValueDiff; 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; @@ -30,16 +30,23 @@ import org.eclipse.core.internal.databinding.identity.IdentitySet; import org.eclipse.core.internal.databinding.property.Util; /** + * @param <S> + * type of the source object + * @param <K> + * type of the keys to the map + * @param <V> + * type of the values in the map * @since 1.2 */ -public class SetSimpleValueObservableMap extends ComputedObservableMap - implements IPropertyObservable { - private SimpleValueProperty detailProperty; +public class SetSimpleValueObservableMap<S, K extends S, V> extends + ComputedObservableMap<K, V> implements + IPropertyObservable<SimpleValueProperty<S, V>> { + private SimpleValueProperty<S, V> detailProperty; - private INativePropertyListener listener; + private INativePropertyListener<S> listener; - private Map cachedValues; - private Set staleKeys; + private Map<K, V> cachedValues; + private Set<K> staleKeys; private boolean updating; @@ -47,8 +54,8 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap * @param keySet * @param valueProperty */ - public SetSimpleValueObservableMap(IObservableSet keySet, - SimpleValueProperty valueProperty) { + public SetSimpleValueObservableMap(IObservableSet<K> keySet, + SimpleValueProperty<S, V> valueProperty) { super(keySet, valueProperty.getValueType()); this.detailProperty = valueProperty; } @@ -56,17 +63,22 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap protected void firstListenerAdded() { if (listener == null) { listener = detailProperty - .adaptListener(new ISimplePropertyListener() { - public void handleEvent(final SimplePropertyEvent event) { + .adaptListener(new ISimplePropertyListener<ValueDiff<V>>() { + public void handleEvent( + final SimplePropertyEvent<ValueDiff<V>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { + // TODO do we need to type the source as + // well? + @SuppressWarnings("unchecked") + K source = (K) event.getSource(); if (event.type == SimplePropertyEvent.CHANGE) { - notifyIfChanged(event.getSource()); + notifyIfChanged(source); } else if (event.type == SimplePropertyEvent.STALE) { boolean wasStale = !staleKeys .isEmpty(); - staleKeys.add(event.getSource()); + staleKeys.add(source); if (!wasStale) fireStale(); } @@ -76,8 +88,8 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap } }); } - cachedValues = new IdentityMap(); - staleKeys = new IdentitySet(); + cachedValues = new IdentityMap<K, V>(); + staleKeys = new IdentitySet<K>(); super.firstListenerAdded(); } @@ -89,7 +101,7 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap staleKeys = null; } - protected void hookListener(Object addedKey) { + protected void hookListener(K addedKey) { if (cachedValues != null) { cachedValues.put(addedKey, detailProperty.getValue(addedKey)); if (listener != null) @@ -97,7 +109,7 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap } } - protected void unhookListener(Object removedKey) { + protected void unhookListener(K removedKey) { if (cachedValues != null) { if (listener != null) listener.removeFrom(removedKey); @@ -106,12 +118,16 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap } } - protected Object doGet(Object key) { - return detailProperty.getValue(key); + @SuppressWarnings("unchecked") + protected V doGet(Object key) { + // NOTE/TODO: This is unsafe and may cause ClassCastExceptions in later + // code + // if this map is queried with keys that are not of type S + return detailProperty.getValue((S) key); } - protected Object doPut(Object key, Object value) { - Object oldValue = detailProperty.getValue(key); + protected V doPut(K key, V value) { + V oldValue = detailProperty.getValue(key); updating = true; try { @@ -125,10 +141,10 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap return oldValue; } - private void notifyIfChanged(Object key) { + private void notifyIfChanged(K key) { if (cachedValues != null) { - Object oldValue = cachedValues.get(key); - Object newValue = detailProperty.getValue(key); + V oldValue = cachedValues.get(key); + V newValue = detailProperty.getValue(key); if (!Util.equals(oldValue, newValue) || staleKeys.contains(key)) { cachedValues.put(key, newValue); staleKeys.remove(key); @@ -142,7 +158,7 @@ public class SetSimpleValueObservableMap extends ComputedObservableMap return keySet(); } - public IProperty getProperty() { + public SimpleValueProperty<S, V> getProperty() { return detailProperty; } diff --git a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SimplePropertyObservableValue.java b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SimplePropertyObservableValue.java index 59ae670a..e4c34b0b 100644 --- a/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SimplePropertyObservableValue.java +++ b/bundles/org.eclipse.core.databinding.property/src/org/eclipse/core/internal/databinding/property/value/SimplePropertyObservableValue.java @@ -18,7 +18,6 @@ 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.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; @@ -26,27 +25,32 @@ import org.eclipse.core.databinding.property.value.SimpleValueProperty; import org.eclipse.core.internal.databinding.property.Util; /** + * @param <S> + * type of the source object + * @param <T> + * type of the value of the property * @since 1.2 * */ -public class SimplePropertyObservableValue extends AbstractObservableValue - implements IPropertyObservable { - private Object source; - private SimpleValueProperty property; +public class SimplePropertyObservableValue<S, T> extends + AbstractObservableValue<T> implements + IPropertyObservable<SimpleValueProperty<S, T>> { + private S source; + private SimpleValueProperty<S, T> property; private boolean updating = false; - private Object cachedValue; + private T cachedValue; private boolean stale; - private INativePropertyListener listener; + private INativePropertyListener<S> listener; /** * @param realm * @param source * @param property */ - public SimplePropertyObservableValue(Realm realm, Object source, - SimpleValueProperty property) { + public SimplePropertyObservableValue(Realm realm, S source, + SimpleValueProperty<S, T> property) { super(realm); this.source = source; this.property = property; @@ -56,14 +60,14 @@ public class SimplePropertyObservableValue extends AbstractObservableValue if (!isDisposed()) { if (listener == null) { listener = property - .adaptListener(new ISimplePropertyListener() { + .adaptListener(new ISimplePropertyListener<ValueDiff<T>>() { public void handleEvent( - final SimplePropertyEvent event) { + final SimplePropertyEvent<ValueDiff<T>> event) { if (!isDisposed() && !updating) { getRealm().exec(new Runnable() { public void run() { if (event.type == SimplePropertyEvent.CHANGE) { - notifyIfChanged((ValueDiff) event.diff); + notifyIfChanged(event.diff); } else if (event.type == SimplePropertyEvent.STALE && !stale) { stale = true; @@ -93,12 +97,12 @@ public class SimplePropertyObservableValue extends AbstractObservableValue stale = false; } - protected Object doGetValue() { + protected T doGetValue() { notifyIfChanged(null); return property.getValue(source); } - protected void doSetValue(Object value) { + protected void doSetValue(T value) { updating = true; try { property.setValue(source, value); @@ -109,10 +113,10 @@ public class SimplePropertyObservableValue extends AbstractObservableValue notifyIfChanged(null); } - private void notifyIfChanged(ValueDiff diff) { + private void notifyIfChanged(ValueDiff<T> diff) { if (hasListeners()) { - Object oldValue = cachedValue; - Object newValue = cachedValue = property.getValue(source); + T oldValue = cachedValue; + T newValue = cachedValue = property.getValue(source); if (diff == null) diff = Diffs.createValueDiff(oldValue, newValue); if (!Util.equals(oldValue, newValue) || stale) { @@ -130,7 +134,7 @@ public class SimplePropertyObservableValue extends AbstractObservableValue return source; } - public IProperty getProperty() { + public SimpleValueProperty<S, T> getProperty() { return property; } diff --git a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/IdentityMapTest.java b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/IdentityMapTest.java index c393697e..0d9bdda0 100644 --- a/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/IdentityMapTest.java +++ b/tests/org.eclipse.jface.tests.databinding/src/org/eclipse/core/tests/internal/databinding/IdentityMapTest.java @@ -33,12 +33,26 @@ public class IdentityMapTest extends TestCase { Object key; Object value; + Map.Entry entry; protected void setUp() throws Exception { super.setUp(); map = new IdentityMap(); key = new Object(); value = new Object(); + entry = new Map.Entry() { + public Object getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object arg0) { + throw new UnsupportedOperationException(); + } + }; } public void testConstructor_NullComparer() { @@ -290,7 +304,7 @@ public class IdentityMapTest extends TestCase { public void testEntrySet_Add() { try { - map.entrySet().add(key); + map.entrySet().add(entry); fail("Expected UnsupportedOperationException"); } catch (UnsupportedOperationException expected) { } |