KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > databinding > observable > Diffs


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.core.databinding.observable;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import org.eclipse.core.databinding.observable.list.ListDiff;
24 import org.eclipse.core.databinding.observable.list.ListDiffEntry;
25 import org.eclipse.core.databinding.observable.map.MapDiff;
26 import org.eclipse.core.databinding.observable.set.SetDiff;
27 import org.eclipse.core.databinding.observable.value.ValueDiff;
28 import org.eclipse.core.internal.databinding.Util;
29
30 /**
31  * @since 1.0
32  *
33  */

34 public class Diffs {
35
36     /**
37      * @param oldList
38      * @param newList
39      * @return the differences between oldList and newList
40      */

41     public static ListDiff computeListDiff(List JavaDoc oldList, List JavaDoc newList) {
42         List JavaDoc diffEntries = new ArrayList JavaDoc();
43         createListDiffs(new ArrayList JavaDoc(oldList), newList, diffEntries);
44         ListDiff listDiff = createListDiff((ListDiffEntry[]) diffEntries
45                 .toArray(new ListDiffEntry[diffEntries.size()]));
46         return listDiff;
47     }
48     
49     /**
50      * adapted from EMF's ListDifferenceAnalyzer
51      */

52     private static void createListDiffs(List JavaDoc oldList, List JavaDoc newList,
53             List JavaDoc listDiffs) {
54         int index = 0;
55         for (Iterator JavaDoc it = newList.iterator(); it.hasNext();) {
56             Object JavaDoc newObject = it.next();
57             if (oldList.size() <= index) {
58                 listDiffs.add(createListDiffEntry(index, true, newObject));
59             } else {
60                 boolean done;
61                 do {
62                     done = true;
63                     Object JavaDoc targetObject = oldList.get(index);
64                     if (targetObject == null ? newObject != null
65                             : !targetObject.equals(newObject)) {
66                         int position = listIndexOf(oldList, newObject, index);
67                         if (position != -1) {
68                             int targetIndex = listIndexOf(newList,
69                                     targetObject, index);
70                             if (targetIndex == -1) {
71                                 listDiffs.add(createListDiffEntry(index, false, targetObject));
72                                 oldList.remove(index);
73                                 done = false;
74                             } else if (targetIndex > position) {
75                                 if (oldList.size() <= targetIndex) {
76                                     targetIndex = oldList.size() - 1;
77                                 }
78                                 listDiffs.add(createListDiffEntry(index, false, newObject));
79                                 oldList.remove(index);
80                                 listDiffs.add(createListDiffEntry(targetIndex, true, newObject));
81                                 oldList.add(targetIndex, newObject);
82                                 done = false;
83                             } else {
84                                 listDiffs.add(createListDiffEntry(position, false, newObject));
85                                 oldList.remove(position);
86                                 listDiffs.add(createListDiffEntry(index, true, newObject));
87                                 oldList.add(index, newObject);
88                             }
89                         } else {
90                             oldList.add(index, newObject);
91                             listDiffs.add(createListDiffEntry(index, true, newObject));
92                         }
93                     }
94                 } while (!done);
95             }
96             ++index;
97         }
98         for (int i = oldList.size(); i > index;) {
99             listDiffs.add(createListDiffEntry(--i, false, oldList.get(i)));
100         }
101     }
102
103     /**
104      * @param list
105      * @param object
106      * @param index
107      * @return the index, or -1 if not found
108      */

109     private static int listIndexOf(List JavaDoc list, Object JavaDoc object, int index) {
110         int size = list.size();
111         for (int i=index; i<size;i++) {
112             Object JavaDoc candidate = list.get(i);
113             if (candidate==null ? object==null : candidate.equals(object)) {
114                 return i;
115             }
116         }
117         return -1;
118     }
119
120     /**
121      * Checks whether the two objects are <code>null</code> -- allowing for
122      * <code>null</code>.
123      *
124      * @param left
125      * The left object to compare; may be <code>null</code>.
126      * @param right
127      * The right object to compare; may be <code>null</code>.
128      * @return <code>true</code> if the two objects are equivalent;
129      * <code>false</code> otherwise.
130      */

131     public static final boolean equals(final Object JavaDoc left, final Object JavaDoc right) {
132         return left == null ? right == null : ((right != null) && left
133                 .equals(right));
134     }
135
136     /**
137      * @param oldSet
138      * @param newSet
139      * @return a set diff
140      */

141     public static SetDiff computeSetDiff(Set JavaDoc oldSet, Set JavaDoc newSet) {
142         Set JavaDoc additions = new HashSet JavaDoc(newSet);
143         additions.removeAll(oldSet);
144         Set JavaDoc removals = new HashSet JavaDoc(oldSet);
145         removals.removeAll(newSet);
146         return createSetDiff(additions, removals);
147     }
148
149     /**
150      * Computes the difference between two maps.
151      *
152      * @param oldMap
153      * @param newMap
154      * @return a map diff representing the changes needed to turn oldMap into
155      * newMap
156      */

157     public static MapDiff computeMapDiff(Map JavaDoc oldMap, Map JavaDoc newMap) {
158         // starts out with all keys from the new map, we will remove keys from
159
// the old map as we go
160
final Set JavaDoc addedKeys = new HashSet JavaDoc(newMap.keySet());
161         final Set JavaDoc removedKeys = new HashSet JavaDoc();
162         final Set JavaDoc changedKeys = new HashSet JavaDoc();
163         final Map JavaDoc oldValues = new HashMap JavaDoc();
164         final Map JavaDoc newValues = new HashMap JavaDoc();
165         for (Iterator JavaDoc it = oldMap.keySet().iterator(); it.hasNext();) {
166             Object JavaDoc oldKey = it.next();
167             if (addedKeys.remove(oldKey)) {
168                 // potentially changed key since it is in oldMap and newMap
169
Object JavaDoc oldValue = oldMap.get(oldKey);
170                 Object JavaDoc newValue = newMap.get(oldKey);
171                 if (!Util.equals(oldValue, newValue)) {
172                     changedKeys.add(oldKey);
173                     oldValues.put(oldKey, oldValue);
174                     newValues.put(oldKey, newValue);
175                 }
176             } else {
177                 removedKeys.add(oldKey);
178                 oldValues.put(oldKey, oldMap.get(oldKey));
179             }
180         }
181         for (Iterator JavaDoc it = addedKeys.iterator(); it.hasNext();) {
182             Object JavaDoc newKey = it.next();
183             newValues.put(newKey, newMap.get(newKey));
184         }
185         return new MapDiff() {
186             public Set JavaDoc getAddedKeys() {
187                 return addedKeys;
188             }
189
190             public Set JavaDoc getChangedKeys() {
191                 return changedKeys;
192             }
193
194             public Set JavaDoc getRemovedKeys() {
195                 return removedKeys;
196             }
197
198             public Object JavaDoc getNewValue(Object JavaDoc key) {
199                 return newValues.get(key);
200             }
201
202             public Object JavaDoc getOldValue(Object JavaDoc key) {
203                 return oldValues.get(key);
204             }
205         };
206     }
207     
208     /**
209      * @param oldValue
210      * @param newValue
211      * @return a value diff
212      */

213     public static ValueDiff createValueDiff(final Object JavaDoc oldValue,
214             final Object JavaDoc newValue) {
215         return new ValueDiff() {
216
217             public Object JavaDoc getOldValue() {
218                 return oldValue;
219             }
220
221             public Object JavaDoc getNewValue() {
222                 return newValue;
223             }
224         };
225     }
226
227     /**
228      * @param additions
229      * @param removals
230      * @return a set diff
231      */

232     public static SetDiff createSetDiff(Set JavaDoc additions, Set JavaDoc removals) {
233         final Set JavaDoc unmodifiableAdditions = Collections
234                 .unmodifiableSet(additions);
235         final Set JavaDoc unmodifiableRemovals = Collections.unmodifiableSet(removals);
236         return new SetDiff() {
237
238             public Set JavaDoc getAdditions() {
239                 return unmodifiableAdditions;
240             }
241
242             public Set JavaDoc getRemovals() {
243                 return unmodifiableRemovals;
244             }
245         };
246     }
247
248     /**
249      * @param difference
250      * @return a list diff with one differing entry
251      */

252     public static ListDiff createListDiff(ListDiffEntry difference) {
253         return createListDiff(new ListDiffEntry[] { difference });
254     }
255
256     /**
257      * @param difference1
258      * @param difference2
259      * @return a list diff with two differing entries
260      */

261     public static ListDiff createListDiff(ListDiffEntry difference1,
262             ListDiffEntry difference2) {
263         return createListDiff(new ListDiffEntry[] { difference1, difference2 });
264     }
265
266     /**
267      * @param differences
268      * @return a list diff with the given entries
269      */

270     public static ListDiff createListDiff(final ListDiffEntry[] differences) {
271         return new ListDiff() {
272             public ListDiffEntry[] getDifferences() {
273                 return differences;
274             }
275         };
276     }
277
278     /**
279      * @param position
280      * @param isAddition
281      * @param element
282      * @return a list diff entry
283      */

284     public static ListDiffEntry createListDiffEntry(final int position,
285             final boolean isAddition, final Object JavaDoc element) {
286         return new ListDiffEntry() {
287
288             public int getPosition() {
289                 return position;
290             }
291
292             public boolean isAddition() {
293                 return isAddition;
294             }
295
296             public Object JavaDoc getElement() {
297                 return element;
298             }
299         };
300     }
301
302     /**
303      * @param addedKey
304      * @param newValue
305      * @return a map diff
306      */

307     public static MapDiff createMapDiffSingleAdd(final Object JavaDoc addedKey,
308             final Object JavaDoc newValue) {
309         return new MapDiff() {
310
311             public Set JavaDoc getAddedKeys() {
312                 return Collections.singleton(addedKey);
313             }
314
315             public Set JavaDoc getChangedKeys() {
316                 return Collections.EMPTY_SET;
317             }
318
319             public Object JavaDoc getNewValue(Object JavaDoc key) {
320                 return newValue;
321             }
322
323             public Object JavaDoc getOldValue(Object JavaDoc key) {
324                 return null;
325             }
326
327             public Set JavaDoc getRemovedKeys() {
328                 return Collections.EMPTY_SET;
329             }
330         };
331     }
332
333     /**
334      * @param existingKey
335      * @param oldValue
336      * @param newValue
337      * @return a map diff
338      */

339     public static MapDiff createMapDiffSingleChange(final Object JavaDoc existingKey,
340             final Object JavaDoc oldValue, final Object JavaDoc newValue) {
341         return new MapDiff() {
342
343             public Set JavaDoc getAddedKeys() {
344                 return Collections.EMPTY_SET;
345             }
346
347             public Set JavaDoc getChangedKeys() {
348                 return Collections.singleton(existingKey);
349             }
350
351             public Object JavaDoc getNewValue(Object JavaDoc key) {
352                 return newValue;
353             }
354
355             public Object JavaDoc getOldValue(Object JavaDoc key) {
356                 return oldValue;
357             }
358
359             public Set JavaDoc getRemovedKeys() {
360                 return Collections.EMPTY_SET;
361             }
362         };
363     }
364
365     /**
366      * @param removedKey
367      * @param oldValue
368      * @return a map diff
369      */

370     public static MapDiff createMapDiffSingleRemove(final Object JavaDoc removedKey,
371             final Object JavaDoc oldValue) {
372         return new MapDiff() {
373
374             public Set JavaDoc getAddedKeys() {
375                 return Collections.EMPTY_SET;
376             }
377
378             public Set JavaDoc getChangedKeys() {
379                 return Collections.EMPTY_SET;
380             }
381
382             public Object JavaDoc getNewValue(Object JavaDoc key) {
383                 return null;
384             }
385
386             public Object JavaDoc getOldValue(Object JavaDoc key) {
387                 return oldValue;
388             }
389
390             public Set JavaDoc getRemovedKeys() {
391                 return Collections.singleton(removedKey);
392             }
393         };
394     }
395
396     /**
397      * @param copyOfOldMap
398      * @return a map diff
399      */

400     public static MapDiff createMapDiffRemoveAll(final Map JavaDoc copyOfOldMap) {
401         return new MapDiff() {
402
403             public Set JavaDoc getAddedKeys() {
404                 return Collections.EMPTY_SET;
405             }
406
407             public Set JavaDoc getChangedKeys() {
408                 return Collections.EMPTY_SET;
409             }
410
411             public Object JavaDoc getNewValue(Object JavaDoc key) {
412                 return null;
413             }
414
415             public Object JavaDoc getOldValue(Object JavaDoc key) {
416                 return copyOfOldMap.get(key);
417             }
418
419             public Set JavaDoc getRemovedKeys() {
420                 return copyOfOldMap.keySet();
421             }
422         };
423     }
424
425     /**
426      * @param addedKeys
427      * @param removedKeys
428      * @param changedKeys
429      * @param oldValues
430      * @param newValues
431      * @return a map diff
432      */

433     public static MapDiff createMapDiff(final Set JavaDoc addedKeys,
434             final Set JavaDoc removedKeys, final Set JavaDoc changedKeys, final Map JavaDoc oldValues,
435             final Map JavaDoc newValues) {
436         return new MapDiff() {
437
438             public Set JavaDoc getAddedKeys() {
439                 return addedKeys;
440             }
441
442             public Set JavaDoc getChangedKeys() {
443                 return changedKeys;
444             }
445
446             public Object JavaDoc getNewValue(Object JavaDoc key) {
447                 return newValues.get(key);
448             }
449
450             public Object JavaDoc getOldValue(Object JavaDoc key) {
451                 return oldValues.get(key);
452             }
453
454             public Set JavaDoc getRemovedKeys() {
455                 return removedKeys;
456             }
457         };
458     }
459     
460 }
461
Popular Tags