Mercurial > projects > dwt2
view org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/Diffs.d @ 96:b74ac5dfcc06
package to module and java.lang.all import
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 21 Apr 2009 11:03:33 +0200 |
parents | 6208d4f6a277 |
children |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2006, 2008 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 * Matthew Hall - bug 226216 *******************************************************************************/ module org.eclipse.core.databinding.observable.Diffs; import java.lang.all; import java.util.ArrayList; 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 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; import org.eclipse.core.internal.databinding.Util; /** * @since 1.0 * */ public class Diffs { /** * @param oldList * @param newList * @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(cast(ListDiffEntry[]) diffEntries .toArray(new ListDiffEntry[diffEntries.size()])); return listDiff; } /** * adapted from EMF's ListDifferenceAnalyzer */ private static void createListDiffs(List oldList, List newList, List listDiffs) { int index = 0; for (Iterator it = newList.iterator(); it.hasNext();) { Object newValue = it.next(); if (oldList.size() <= index) { // append newValue to newList listDiffs.add(createListDiffEntry(index, true, newValue)); } else { bool done; do { done = true; Object oldValue = oldList.get(index); if (oldValue is null ? newValue !is null : !oldValue.equals(newValue)) { int oldIndexOfNewValue = listIndexOf(oldList, newValue, index); if (oldIndexOfNewValue !is -1) { int newIndexOfOldValue = listIndexOf(newList, oldValue, index); if (newIndexOfOldValue is -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 int listIndexOf(List list, Object object, int index) { int size = list.size(); for (int i=index; i<size;i++) { Object candidate = list.get(i); if (candidateisnull ? objectisnull : 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. */ public static final override equals_t opEquals(final Object left, final Object right) { return left is null ? right is null : ((right !is null) && left .equals(right)); } /** * @param oldSet * @param newSet * @return a set diff */ public static SetDiff computeSetDiff(Set oldSet, Set newSet) { Set additions = new HashSet(newSet); additions.removeAll(oldSet); Set removals = new HashSet(oldSet); removals.removeAll(newSet); return createSetDiff(additions, removals); } /** * Computes the difference between two maps. * * @param oldMap * @param newMap * @return a map diff representing the changes needed to turn oldMap into * newMap */ public static MapDiff computeMapDiff(Map oldMap, Map 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 = cast(Entry) it.next(); Object 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); if (!Util.equals(oldValue, newValue)) { changedKeys.add(oldKey); oldValues.put(oldKey, oldValue); newValues.put(oldKey, newValue); } } else { removedKeys.add(oldKey); oldValues.put(oldKey, oldEntry.getValue()); } } for (Iterator it = addedKeys.iterator(); it.hasNext();) { Object newKey = it.next(); newValues.put(newKey, newMap.get(newKey)); } return new class() MapDiff { public Set getAddedKeys() { return addedKeys; } public Set getChangedKeys() { return changedKeys; } public Set getRemovedKeys() { return removedKeys; } public Object getNewValue(Object key) { return newValues.get(key); } public Object getOldValue(Object key) { return oldValues.get(key); } }; } /** * @param oldValue * @param newValue * @return a value diff */ public static ValueDiff createValueDiff(final Object oldValue, final Object newValue) { return new class() ValueDiff { public Object getOldValue() { return oldValue; } public Object getNewValue() { return newValue; } }; } /** * @param additions * @param removals * @return a set diff */ public static SetDiff createSetDiff(Set additions, Set removals) { final Set unmodifiableAdditions = Collections .unmodifiableSet(additions); final Set unmodifiableRemovals = Collections.unmodifiableSet(removals); return new class() SetDiff { public Set getAdditions() { return unmodifiableAdditions; } public Set getRemovals() { return unmodifiableRemovals; } }; } /** * @param difference * @return a list diff with one differing entry */ public static ListDiff createListDiff(ListDiffEntry difference) { return createListDiff(new ListDiffEntry[] { difference }); } /** * @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 }); } /** * @param differences * @return a list diff with the given entries */ public static ListDiff createListDiff(final ListDiffEntry[] differences) { return new class() ListDiff { public ListDiffEntry[] getDifferences() { return differences; } }; } /** * @param position * @param isAddition * @param element * @return a list diff entry */ public static ListDiffEntry createListDiffEntry(final int position, final bool isAddition, final Object element) { return new class() ListDiffEntry { public int getPosition() { return position; } public bool isAddition() { return isAddition; } public Object getElement() { return element; } }; } /** * @param addedKey * @param newValue * @return a map diff */ public static MapDiff createMapDiffSingleAdd(final Object addedKey, final Object newValue) { return new class() MapDiff { public Set getAddedKeys() { return Collections.singleton(addedKey); } public Set getChangedKeys() { return Collections.EMPTY_SET; } public Object getNewValue(Object key) { return newValue; } public Object getOldValue(Object key) { return null; } public Set getRemovedKeys() { return Collections.EMPTY_SET; } }; } /** * @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 class() MapDiff { public Set getAddedKeys() { return Collections.EMPTY_SET; } public Set getChangedKeys() { return Collections.singleton(existingKey); } public Object getNewValue(Object key) { return newValue; } public Object getOldValue(Object key) { return oldValue; } public Set getRemovedKeys() { return Collections.EMPTY_SET; } }; } /** * @param removedKey * @param oldValue * @return a map diff */ public static MapDiff createMapDiffSingleRemove(final Object removedKey, final Object oldValue) { return new class() MapDiff { public Set getAddedKeys() { return Collections.EMPTY_SET; } public Set getChangedKeys() { return Collections.EMPTY_SET; } public Object getNewValue(Object key) { return null; } public Object getOldValue(Object key) { return oldValue; } public Set getRemovedKeys() { return Collections.singleton(removedKey); } }; } /** * @param copyOfOldMap * @return a map diff */ public static MapDiff createMapDiffRemoveAll(final Map copyOfOldMap) { return new class() MapDiff { public Set getAddedKeys() { return Collections.EMPTY_SET; } public Set getChangedKeys() { return Collections.EMPTY_SET; } public Object getNewValue(Object key) { return null; } public Object getOldValue(Object key) { return copyOfOldMap.get(key); } public Set getRemovedKeys() { return copyOfOldMap.keySet(); } }; } /** * @param addedKeys * @param removedKeys * @param changedKeys * @param oldValues * @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 class() MapDiff { public Set getAddedKeys() { return addedKeys; } public Set getChangedKeys() { return changedKeys; } public Object getNewValue(Object key) { return newValues.get(key); } public Object getOldValue(Object key) { return oldValues.get(key); } public Set getRemovedKeys() { return removedKeys; } }; } }