1 11 12 package org.eclipse.core.databinding.observable; 13 14 import java.util.ArrayList ; 15 import java.util.Collections ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 import java.util.Set ; 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 34 public class Diffs { 35 36 41 public static ListDiff computeListDiff(List oldList, List newList) { 42 List diffEntries = new ArrayList (); 43 createListDiffs(new ArrayList (oldList), newList, diffEntries); 44 ListDiff listDiff = createListDiff((ListDiffEntry[]) diffEntries 45 .toArray(new ListDiffEntry[diffEntries.size()])); 46 return listDiff; 47 } 48 49 52 private static void createListDiffs(List oldList, List newList, 53 List listDiffs) { 54 int index = 0; 55 for (Iterator it = newList.iterator(); it.hasNext();) { 56 Object 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 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 109 private static int listIndexOf(List list, Object object, int index) { 110 int size = list.size(); 111 for (int i=index; i<size;i++) { 112 Object candidate = list.get(i); 113 if (candidate==null ? object==null : candidate.equals(object)) { 114 return i; 115 } 116 } 117 return -1; 118 } 119 120 131 public static final boolean equals(final Object left, final Object right) { 132 return left == null ? right == null : ((right != null) && left 133 .equals(right)); 134 } 135 136 141 public static SetDiff computeSetDiff(Set oldSet, Set newSet) { 142 Set additions = new HashSet (newSet); 143 additions.removeAll(oldSet); 144 Set removals = new HashSet (oldSet); 145 removals.removeAll(newSet); 146 return createSetDiff(additions, removals); 147 } 148 149 157 public static MapDiff computeMapDiff(Map oldMap, Map newMap) { 158 final Set addedKeys = new HashSet (newMap.keySet()); 161 final Set removedKeys = new HashSet (); 162 final Set changedKeys = new HashSet (); 163 final Map oldValues = new HashMap (); 164 final Map newValues = new HashMap (); 165 for (Iterator it = oldMap.keySet().iterator(); it.hasNext();) { 166 Object oldKey = it.next(); 167 if (addedKeys.remove(oldKey)) { 168 Object oldValue = oldMap.get(oldKey); 170 Object 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 it = addedKeys.iterator(); it.hasNext();) { 182 Object newKey = it.next(); 183 newValues.put(newKey, newMap.get(newKey)); 184 } 185 return new MapDiff() { 186 public Set getAddedKeys() { 187 return addedKeys; 188 } 189 190 public Set getChangedKeys() { 191 return changedKeys; 192 } 193 194 public Set getRemovedKeys() { 195 return removedKeys; 196 } 197 198 public Object getNewValue(Object key) { 199 return newValues.get(key); 200 } 201 202 public Object getOldValue(Object key) { 203 return oldValues.get(key); 204 } 205 }; 206 } 207 208 213 public static ValueDiff createValueDiff(final Object oldValue, 214 final Object newValue) { 215 return new ValueDiff() { 216 217 public Object getOldValue() { 218 return oldValue; 219 } 220 221 public Object getNewValue() { 222 return newValue; 223 } 224 }; 225 } 226 227 232 public static SetDiff createSetDiff(Set additions, Set removals) { 233 final Set unmodifiableAdditions = Collections 234 .unmodifiableSet(additions); 235 final Set unmodifiableRemovals = Collections.unmodifiableSet(removals); 236 return new SetDiff() { 237 238 public Set getAdditions() { 239 return unmodifiableAdditions; 240 } 241 242 public Set getRemovals() { 243 return unmodifiableRemovals; 244 } 245 }; 246 } 247 248 252 public static ListDiff createListDiff(ListDiffEntry difference) { 253 return createListDiff(new ListDiffEntry[] { difference }); 254 } 255 256 261 public static ListDiff createListDiff(ListDiffEntry difference1, 262 ListDiffEntry difference2) { 263 return createListDiff(new ListDiffEntry[] { difference1, difference2 }); 264 } 265 266 270 public static ListDiff createListDiff(final ListDiffEntry[] differences) { 271 return new ListDiff() { 272 public ListDiffEntry[] getDifferences() { 273 return differences; 274 } 275 }; 276 } 277 278 284 public static ListDiffEntry createListDiffEntry(final int position, 285 final boolean isAddition, final Object 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 getElement() { 297 return element; 298 } 299 }; 300 } 301 302 307 public static MapDiff createMapDiffSingleAdd(final Object addedKey, 308 final Object newValue) { 309 return new MapDiff() { 310 311 public Set getAddedKeys() { 312 return Collections.singleton(addedKey); 313 } 314 315 public Set getChangedKeys() { 316 return Collections.EMPTY_SET; 317 } 318 319 public Object getNewValue(Object key) { 320 return newValue; 321 } 322 323 public Object getOldValue(Object key) { 324 return null; 325 } 326 327 public Set getRemovedKeys() { 328 return Collections.EMPTY_SET; 329 } 330 }; 331 } 332 333 339 public static MapDiff createMapDiffSingleChange(final Object existingKey, 340 final Object oldValue, final Object newValue) { 341 return new MapDiff() { 342 343 public Set getAddedKeys() { 344 return Collections.EMPTY_SET; 345 } 346 347 public Set getChangedKeys() { 348 return Collections.singleton(existingKey); 349 } 350 351 public Object getNewValue(Object key) { 352 return newValue; 353 } 354 355 public Object getOldValue(Object key) { 356 return oldValue; 357 } 358 359 public Set getRemovedKeys() { 360 return Collections.EMPTY_SET; 361 } 362 }; 363 } 364 365 370 public static MapDiff createMapDiffSingleRemove(final Object removedKey, 371 final Object oldValue) { 372 return new MapDiff() { 373 374 public Set getAddedKeys() { 375 return Collections.EMPTY_SET; 376 } 377 378 public Set getChangedKeys() { 379 return Collections.EMPTY_SET; 380 } 381 382 public Object getNewValue(Object key) { 383 return null; 384 } 385 386 public Object getOldValue(Object key) { 387 return oldValue; 388 } 389 390 public Set getRemovedKeys() { 391 return Collections.singleton(removedKey); 392 } 393 }; 394 } 395 396 400 public static MapDiff createMapDiffRemoveAll(final Map copyOfOldMap) { 401 return new MapDiff() { 402 403 public Set getAddedKeys() { 404 return Collections.EMPTY_SET; 405 } 406 407 public Set getChangedKeys() { 408 return Collections.EMPTY_SET; 409 } 410 411 public Object getNewValue(Object key) { 412 return null; 413 } 414 415 public Object getOldValue(Object key) { 416 return copyOfOldMap.get(key); 417 } 418 419 public Set getRemovedKeys() { 420 return copyOfOldMap.keySet(); 421 } 422 }; 423 } 424 425 433 public static MapDiff createMapDiff(final Set addedKeys, 434 final Set removedKeys, final Set changedKeys, final Map oldValues, 435 final Map newValues) { 436 return new MapDiff() { 437 438 public Set getAddedKeys() { 439 return addedKeys; 440 } 441 442 public Set getChangedKeys() { 443 return changedKeys; 444 } 445 446 public Object getNewValue(Object key) { 447 return newValues.get(key); 448 } 449 450 public Object getOldValue(Object key) { 451 return oldValues.get(key); 452 } 453 454 public Set getRemovedKeys() { 455 return removedKeys; 456 } 457 }; 458 } 459 460 } 461 | Popular Tags |