| /******************************************************************************* |
| * Copyright (c) 2006, 2015 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Matthew Hall - bug 226216 |
| * Stefan Xenos <sxenos@gmail.com> - Bug 335792 |
| * Stefan Xenos <sxenos@gmail.com> - Bug 474065 |
| *******************************************************************************/ |
| |
| package org.eclipse.core.databinding.observable; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Objects; |
| import java.util.Set; |
| |
| import org.eclipse.core.databinding.observable.list.ListDiff; |
| import org.eclipse.core.databinding.observable.list.ListDiffEntry; |
| import org.eclipse.core.databinding.observable.map.MapDiff; |
| import org.eclipse.core.databinding.observable.set.SetDiff; |
| import org.eclipse.core.databinding.observable.value.ValueDiff; |
| |
| /** |
| * @since 1.0 |
| * |
| */ |
| public class Diffs { |
| private static final class UnmodifiableListDiff<E> extends ListDiff<E> { |
| private ListDiff<? extends E> toWrap; |
| |
| public UnmodifiableListDiff(ListDiff<? extends E> diff) { |
| this.toWrap = diff; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public ListDiffEntry<E>[] getDifferences() { |
| ListDiffEntry<? extends E>[] original = toWrap.getDifferences(); |
| ListDiffEntry<?>[] result = new ListDiffEntry<?>[original.length]; |
| |
| System.arraycopy(original, 0, result, 0, original.length); |
| return (ListDiffEntry<E>[]) result; |
| } |
| } |
| |
| private static final class UnmodifiableSetDiff<E> extends SetDiff<E> { |
| private SetDiff<? extends E> toWrap; |
| |
| public UnmodifiableSetDiff(SetDiff<? extends E> diff) { |
| toWrap = diff; |
| } |
| |
| @Override |
| public Set<E> getAdditions() { |
| return Collections.unmodifiableSet(toWrap.getAdditions()); |
| } |
| |
| @Override |
| public Set<E> getRemovals() { |
| return Collections.unmodifiableSet(toWrap.getRemovals()); |
| } |
| } |
| |
| private static final class UnmodifiableMapDiff<K, V> extends MapDiff<K, V> { |
| private MapDiff<? extends K, ? extends V> toWrap; |
| |
| public UnmodifiableMapDiff(MapDiff<? extends K, ? extends V> diff) { |
| toWrap = diff; |
| } |
| |
| @Override |
| public Set<K> getAddedKeys() { |
| return Collections.unmodifiableSet(toWrap.getAddedKeys()); |
| } |
| |
| @Override |
| public Set<K> getRemovedKeys() { |
| return Collections.unmodifiableSet(toWrap.getRemovedKeys()); |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return Collections.unmodifiableSet(toWrap.getChangedKeys()); |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return toWrap.getOldValue(key); |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return toWrap.getNewValue(key); |
| } |
| } |
| |
| private static final class UnmodifiableValueDiff<E> extends ValueDiff<E> { |
| private ValueDiff<? extends E> toWrap; |
| |
| public UnmodifiableValueDiff(ValueDiff<? extends E> diff) { |
| toWrap = diff; |
| } |
| |
| @Override |
| public E getOldValue() { |
| return toWrap.getOldValue(); |
| } |
| |
| @Override |
| public E getNewValue() { |
| return toWrap.getNewValue(); |
| } |
| } |
| |
| /** |
| * Returns an unmodifiable wrapper on top of the given diff. The returned |
| * diff will suppress any attempt to modify the collections it returns. |
| * Diffs are normally unmodifiable anyway, so this method is mainly used as |
| * a type-safe way to convert a {@code ListDiff<? extends E>} into a |
| * {@code ListDiff<E>}. |
| * |
| * @param diff |
| * the diff to convert |
| * @return an unmodifiable wrapper on top of the given diff |
| * @since 1.6 |
| */ |
| @SuppressWarnings("unchecked") |
| public static <E> ListDiff<E> unmodifiableDiff(ListDiff<? extends E> diff) { |
| // If the diff is already unmodifiable, there's no need to wrap it again |
| if (diff instanceof UnmodifiableListDiff) { |
| return (ListDiff<E>) diff; |
| } |
| |
| return new UnmodifiableListDiff<>(diff); |
| } |
| |
| /** |
| * Returns an unmodifiable wrapper on top of the given diff. The returned |
| * diff will suppress any attempt to modify the collections it returns. |
| * Diffs are normally unmodifiable anyway, so this method is mainly used as |
| * a type-safe way to convert a {@code SetDiff<? extends E>} into a |
| * {@code SetDiff<E>}. |
| * |
| * @param diff |
| * the diff to convert |
| * @return an unmodifiable wrapper on top of the given diff |
| * @since 1.6 |
| */ |
| @SuppressWarnings("unchecked") |
| public static <E> SetDiff<E> unmodifiableDiff(SetDiff<? extends E> diff) { |
| // If the diff is already unmodifiable, there's no need to wrap it again |
| if (diff instanceof UnmodifiableSetDiff) { |
| return (SetDiff<E>) diff; |
| } |
| |
| return new UnmodifiableSetDiff<>(diff); |
| } |
| |
| /** |
| * Returns an unmodifiable wrapper on top of the given diff. The returned |
| * diff will suppress any attempt to modify the collections it returns. |
| * Diffs are normally unmodifiable anyway, so this method is mainly used as |
| * a type-safe way to convert a {@code MapDiff<? extends K, ? extends V>} |
| * into a {@code MapDiff<K,V>}. |
| * |
| * @param diff |
| * the diff to convert |
| * @return an unmodifiable wrapper on top of the given diff |
| * @since 1.6 |
| */ |
| @SuppressWarnings("unchecked") |
| public static <K, V> MapDiff<K, V> unmodifiableDiff(MapDiff<? extends K, ? extends V> diff) { |
| // If the diff is already unmodifiable, there's no need to wrap it again |
| if (diff instanceof UnmodifiableMapDiff) { |
| return (MapDiff<K, V>) diff; |
| } |
| |
| return new UnmodifiableMapDiff<>(diff); |
| } |
| |
| /** |
| * Returns an unmodifiable wrapper on top of the given diff. The returned |
| * diff will suppress any attempt to modify the collections it returns. |
| * Diffs are normally unmodifiable anyway, so this method is mainly used as |
| * a type-safe way to convert a {@code ValueDiff<? extends V>} into a |
| * {@code ValueDiff<V>}. |
| * |
| * @param diff |
| * the diff to convert |
| * @return an unmodifiable wrapper on top of the given diff |
| * @since 1.6 |
| */ |
| @SuppressWarnings("unchecked") |
| public static <V> ValueDiff<V> unmodifiableDiff(ValueDiff<? extends V> diff) { |
| // If the diff is already unmodifiable, there's no need to wrap it again |
| if (diff instanceof UnmodifiableValueDiff) { |
| return (ValueDiff<V>) diff; |
| } |
| |
| return new UnmodifiableValueDiff<>(diff); |
| } |
| |
| /** |
| * Returns a {@link ListDiff} describing the change between the specified |
| * old and new list states. |
| * |
| * @param <E> |
| * the list element type |
| * |
| * @param oldList |
| * the old list state |
| * @param newList |
| * the new list state |
| * @return the differences between oldList and newList |
| * @since 1.6 |
| */ |
| public static <E> ListDiff<E> computeListDiff(List<? extends E> oldList, List<? extends E> newList) { |
| List<ListDiffEntry<E>> diffEntries = new ArrayList<>(); |
| createListDiffs(new ArrayList<>(oldList), newList, diffEntries); |
| return createListDiff(diffEntries); |
| } |
| |
| /** |
| * Returns a lazily computed {@link ListDiff} describing the change between |
| * the specified old and new list states. |
| * |
| * @param <E> |
| * the list element type |
| * |
| * @param oldList |
| * the old list state |
| * @param newList |
| * the new list state |
| * @return a lazily computed {@link ListDiff} describing the change between |
| * the specified old and new list states. |
| * @since 1.3 |
| */ |
| public static <E> ListDiff<E> computeLazyListDiff(final List<? extends E> oldList, |
| final List<? extends E> newList) { |
| return new ListDiff<E>() { |
| ListDiff<E> lazyDiff; |
| |
| @Override |
| public ListDiffEntry<E>[] getDifferences() { |
| if (lazyDiff == null) { |
| lazyDiff = Diffs.computeListDiff(oldList, newList); |
| } |
| return lazyDiff.getDifferences(); |
| } |
| }; |
| } |
| |
| /** |
| * adapted from EMF's ListDifferenceAnalyzer |
| */ |
| private static <E> void createListDiffs(List<E> oldList, List<? extends E> newList, |
| List<ListDiffEntry<E>> listDiffs) { |
| int index = 0; |
| for (E newValue : newList) { |
| if (oldList.size() <= index) { |
| // append newValue to newList |
| listDiffs.add(createListDiffEntry(index, true, newValue)); |
| } else { |
| boolean done; |
| do { |
| done = true; |
| E oldValue = oldList.get(index); |
| if (oldValue == null ? newValue != null : !oldValue |
| .equals(newValue)) { |
| int oldIndexOfNewValue = listIndexOf(oldList, newValue, |
| index); |
| if (oldIndexOfNewValue != -1) { |
| int newIndexOfOldValue = listIndexOf(newList, |
| oldValue, index); |
| if (newIndexOfOldValue == -1) { |
| // removing oldValue from list[index] |
| listDiffs.add(createListDiffEntry(index, false, |
| oldValue)); |
| oldList.remove(index); |
| done = false; |
| } else if (newIndexOfOldValue > oldIndexOfNewValue) { |
| // moving oldValue from list[index] to |
| // [newIndexOfOldValue] |
| if (oldList.size() <= newIndexOfOldValue) { |
| // The element cannot be moved to the |
| // correct index |
| // now, however later iterations will insert |
| // elements |
| // in front of it, eventually moving it into |
| // the |
| // correct spot. |
| newIndexOfOldValue = oldList.size() - 1; |
| } |
| listDiffs.add(createListDiffEntry(index, false, |
| oldValue)); |
| oldList.remove(index); |
| listDiffs.add(createListDiffEntry( |
| newIndexOfOldValue, true, oldValue)); |
| oldList.add(newIndexOfOldValue, oldValue); |
| done = false; |
| } else { |
| // move newValue from list[oldIndexOfNewValue] |
| // to [index] |
| listDiffs.add(createListDiffEntry( |
| oldIndexOfNewValue, false, newValue)); |
| oldList.remove(oldIndexOfNewValue); |
| listDiffs.add(createListDiffEntry(index, true, |
| newValue)); |
| oldList.add(index, newValue); |
| } |
| } else { |
| // add newValue at list[index] |
| oldList.add(index, newValue); |
| listDiffs.add(createListDiffEntry(index, true, |
| newValue)); |
| } |
| } |
| } while (!done); |
| } |
| ++index; |
| } |
| for (int i = oldList.size(); i > index;) { |
| // remove excess trailing elements not present in newList |
| listDiffs.add(createListDiffEntry(--i, false, oldList.get(i))); |
| } |
| } |
| |
| /** |
| * @param list |
| * @param object |
| * @param index |
| * @return the index, or -1 if not found |
| */ |
| 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); |
| if (candidate == null ? object == null : candidate.equals(object)) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * Checks whether the two objects are <code>null</code> -- allowing for |
| * <code>null</code>. |
| * |
| * @param left The left object to compare; may be <code>null</code>. |
| * @param right The right object to compare; may be <code>null</code>. |
| * @return <code>true</code> if the two objects are equivalent; |
| * <code>false</code> otherwise. |
| * @deprecated Use {@link Objects#equals(Object, Object)} instead |
| */ |
| @Deprecated |
| public static final boolean equals(final Object left, final Object right) { |
| return Objects.equals(left, right); |
| } |
| |
| /** |
| * Returns a {@link SetDiff} describing the change between the specified old and |
| * new set states. |
| * |
| * @param <E> the set element type |
| * |
| * @param oldSet the old set state |
| * @param newSet the new set state |
| * @return a {@link SetDiff} describing the change between the specified old and |
| * new set states. |
| */ |
| public static <E> SetDiff<E> computeSetDiff(Set<? extends E> oldSet, Set<? extends E> newSet) { |
| Set<E> additions = new HashSet<>(newSet); |
| additions.removeAll(oldSet); |
| Set<E> removals = new HashSet<>(oldSet); |
| removals.removeAll(newSet); |
| return createSetDiff(additions, removals); |
| } |
| |
| /** |
| * Returns a lazily computed {@link SetDiff} describing the change between |
| * the specified old and new set states. |
| * |
| * @param <E> |
| * the set element type |
| * |
| * @param oldSet |
| * the old set state |
| * @param newSet |
| * the new set state |
| * @return a lazily computed {@link SetDiff} describing the change between |
| * the specified old and new set states. |
| * @since 1.3 |
| */ |
| public static <E> SetDiff<E> computeLazySetDiff(final Set<? extends E> oldSet, final Set<? extends E> newSet) { |
| return new SetDiff<E>() { |
| |
| private SetDiff<E> lazyDiff; |
| |
| private SetDiff<E> getLazyDiff() { |
| if (lazyDiff == null) { |
| lazyDiff = computeSetDiff(oldSet, newSet); |
| } |
| return lazyDiff; |
| } |
| |
| @Override |
| public Set<E> getAdditions() { |
| return getLazyDiff().getAdditions(); |
| } |
| |
| @Override |
| public Set<E> getRemovals() { |
| return getLazyDiff().getRemovals(); |
| } |
| |
| }; |
| } |
| |
| /** |
| * 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 |
| * the new map state |
| * @return a {@link MapDiff} describing the change between the specified old |
| * and new map states. |
| */ |
| public static <K, V> MapDiff<K, V> computeMapDiff(Map<? extends K, ? extends V> oldMap, |
| Map<? extends K, ? extends V> newMap) { |
| // starts out with all keys from the new map, we will remove keys from |
| // the old map as we go |
| final Set<K> addedKeys = new HashSet<>(newMap.keySet()); |
| final Set<K> removedKeys = new HashSet<>(); |
| final Set<K> changedKeys = new HashSet<>(); |
| final Map<K, V> oldValues = new HashMap<>(); |
| final Map<K, V> newValues = new HashMap<>(); |
| for (Entry<? extends K, ? extends V> oldEntry : oldMap.entrySet()) { |
| K oldKey = oldEntry.getKey(); |
| if (addedKeys.remove(oldKey)) { |
| // potentially changed key since it is in oldMap and newMap |
| V oldValue = oldEntry.getValue(); |
| V newValue = newMap.get(oldKey); |
| if (!Objects.equals(oldValue, newValue)) { |
| changedKeys.add(oldKey); |
| oldValues.put(oldKey, oldValue); |
| newValues.put(oldKey, newValue); |
| } |
| } else { |
| removedKeys.add(oldKey); |
| oldValues.put(oldKey, oldEntry.getValue()); |
| } |
| } |
| for (K newKey : addedKeys) { |
| newValues.put(newKey, newMap.get(newKey)); |
| } |
| return new MapDiff<K, V>() { |
| @Override |
| public Set<K> getAddedKeys() { |
| return addedKeys; |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return changedKeys; |
| } |
| |
| @Override |
| public Set<K> getRemovedKeys() { |
| return removedKeys; |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return newValues.get(key); |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return oldValues.get(key); |
| } |
| }; |
| } |
| |
| /** |
| * 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 |
| * the new map state |
| * @return a lazily computed {@link MapDiff} describing the change between |
| * the specified old and new map states. |
| * @since 1.3 |
| */ |
| public static <K, V> MapDiff<K, V> computeLazyMapDiff(final Map<? extends K, ? extends V> oldMap, |
| final Map<? extends K, ? extends V> newMap) { |
| return new MapDiff<K, V>() { |
| |
| private MapDiff<K, V> lazyDiff; |
| |
| private MapDiff<K, V> getLazyDiff() { |
| if (lazyDiff == null) { |
| lazyDiff = computeMapDiff(oldMap, newMap); |
| } |
| return lazyDiff; |
| } |
| |
| @Override |
| public Set<K> getAddedKeys() { |
| return getLazyDiff().getAddedKeys(); |
| } |
| |
| @Override |
| public Set<K> getRemovedKeys() { |
| return getLazyDiff().getRemovedKeys(); |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return getLazyDiff().getChangedKeys(); |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return getLazyDiff().getOldValue(key); |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return getLazyDiff().getNewValue(key); |
| } |
| |
| }; |
| } |
| |
| /** |
| * Creates a diff between two values |
| * |
| * @param <T> |
| * the value type |
| * @param oldValue |
| * @param newValue |
| * @return a value diff |
| */ |
| public static <T> ValueDiff<T> createValueDiff(final T oldValue, final T newValue) { |
| return new ValueDiff<T>() { |
| |
| @Override |
| public T getOldValue() { |
| return oldValue; |
| } |
| |
| @Override |
| public T getNewValue() { |
| return newValue; |
| } |
| }; |
| } |
| |
| /** |
| * @param <E> |
| * the set element type |
| * @param additions |
| * @param removals |
| * @return a set diff |
| */ |
| public static <E> SetDiff<E> createSetDiff(Set<? extends E> additions, Set<? extends E> removals) { |
| final Set<E> unmodifiableAdditions = Collections |
| .unmodifiableSet(additions); |
| final Set<E> unmodifiableRemovals = Collections |
| .unmodifiableSet(removals); |
| return new SetDiff<E>() { |
| |
| @Override |
| public Set<E> getAdditions() { |
| return unmodifiableAdditions; |
| } |
| |
| @Override |
| public Set<E> getRemovals() { |
| return unmodifiableRemovals; |
| } |
| }; |
| } |
| |
| /** |
| * @param <E> |
| * the list element type |
| * @param difference |
| * @return a list diff with one differing entry |
| */ |
| public static <E> ListDiff<E> createListDiff(ListDiffEntry<E> difference) { |
| return createListDiff(Collections.singletonList(difference)); |
| } |
| |
| /** |
| * @param <E> |
| * the list element type |
| * @param difference1 |
| * @param difference2 |
| * @return a list diff with two differing entries |
| */ |
| public static <E> ListDiff<E> createListDiff(ListDiffEntry<E> difference1, |
| ListDiffEntry<E> difference2) { |
| List<ListDiffEntry<E>> differences = new ArrayList<>(2); |
| differences.add(difference1); |
| differences.add(difference2); |
| return createListDiff(differences); |
| } |
| |
| /** |
| * Creates a new ListDiff object given its constituent ListDiffEntry |
| * objects. |
| * <p> |
| * 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. Use the |
| * form below which takes a properly parameterized List. |
| * |
| * @param <E> |
| * the list element type |
| * @param differences |
| * @return a list diff with the given entries |
| */ |
| @SafeVarargs |
| public static <E> ListDiff<E> createListDiff(final ListDiffEntry<E>... differences) { |
| return new ListDiff<E>() { |
| @Override |
| public ListDiffEntry<E>[] getDifferences() { |
| return differences; |
| } |
| }; |
| } |
| |
| /** |
| * Creates a new ListDiff object given its constituent ListDiffEntry |
| * objects. |
| * |
| * @param <E> |
| * the list element type |
| * @param differences |
| * @return a list diff with the given entries |
| * @since 1.6 |
| */ |
| public static <E> ListDiff<E> createListDiff(final List<ListDiffEntry<E>> differences) { |
| final ListDiffEntry<E>[] differencesArray = differences.toArray(new ListDiffEntry[differences.size()]); |
| return new ListDiff<E>() { |
| @Override |
| public ListDiffEntry<E>[] getDifferences() { |
| return differencesArray; |
| } |
| }; |
| } |
| |
| /** |
| * @param <E> |
| * the list element type |
| * @param position |
| * @param isAddition |
| * @param element |
| * @return a list diff entry |
| */ |
| public static <E> ListDiffEntry<E> createListDiffEntry(final int position, |
| final boolean isAddition, final E element) { |
| return new ListDiffEntry<E>() { |
| |
| @Override |
| public int getPosition() { |
| return position; |
| } |
| |
| @Override |
| public boolean isAddition() { |
| return isAddition; |
| } |
| |
| @Override |
| public E getElement() { |
| return element; |
| } |
| }; |
| } |
| |
| /** |
| * Creates a MapDiff representing the addition of a single added key |
| * |
| * @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 <K, V> MapDiff<K, V> createMapDiffSingleAdd(final K addedKey, |
| final V newValue) { |
| return new MapDiff<K, V>() { |
| |
| @Override |
| public Set<K> getAddedKeys() { |
| return Collections.singleton(addedKey); |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return newValue; |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return null; |
| } |
| |
| @Override |
| 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 <K, V> MapDiff<K, V> createMapDiffSingleChange( |
| final K existingKey, final V oldValue, final V newValue) { |
| return new MapDiff<K, V>() { |
| |
| @Override |
| public Set<K> getAddedKeys() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return Collections.singleton(existingKey); |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return newValue; |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return oldValue; |
| } |
| |
| @Override |
| 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 <K, V> MapDiff<K, V> createMapDiffSingleRemove( |
| final K removedKey, final V oldValue) { |
| return new MapDiff<K, V>() { |
| |
| @Override |
| public Set<K> getAddedKeys() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return null; |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return oldValue; |
| } |
| |
| @Override |
| 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 <K, V> MapDiff<K, V> createMapDiffRemoveAll( |
| final Map<K, V> copyOfOldMap) { |
| return new MapDiff<K, V>() { |
| |
| @Override |
| public Set<K> getAddedKeys() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return Collections.emptySet(); |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return null; |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return copyOfOldMap.get(key); |
| } |
| |
| @Override |
| 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 |
| * @param oldValues |
| * @param newValues |
| * @return a map diff |
| */ |
| public static <K, V> MapDiff<K, V> createMapDiff(Set<? extends K> addedKeys, Set<? extends K> removedKeys, |
| Set<? extends K> changedKeys, final Map<? extends K, ? extends V> oldValues, |
| final Map<? extends K, ? extends V> newValues) { |
| final Set<K> finalAddedKeys = Collections.unmodifiableSet(addedKeys); |
| final Set<K> finalRemovedKeys = Collections.unmodifiableSet(removedKeys); |
| final Set<K> finalChangedKeys = Collections.unmodifiableSet(changedKeys); |
| |
| return new MapDiff<K, V>() { |
| @Override |
| public Set<K> getAddedKeys() { |
| return finalAddedKeys; |
| } |
| |
| @Override |
| public Set<K> getChangedKeys() { |
| return finalChangedKeys; |
| } |
| |
| @Override |
| public V getNewValue(Object key) { |
| return newValues.get(key); |
| } |
| |
| @Override |
| public V getOldValue(Object key) { |
| return oldValues.get(key); |
| } |
| |
| @Override |
| public Set<K> getRemovedKeys() { |
| return finalRemovedKeys; |
| } |
| }; |
| } |
| } |