1 11 package org.eclipse.team.core.diff.provider; 12 13 import java.util.*; 14 15 import org.eclipse.core.resources.IResource; 16 import org.eclipse.core.runtime.*; 17 import org.eclipse.core.runtime.jobs.ILock; 18 import org.eclipse.core.runtime.jobs.Job; 19 import org.eclipse.team.core.diff.*; 20 import org.eclipse.team.internal.core.Policy; 21 import org.eclipse.team.internal.core.mapping.DiffChangeEvent; 22 import org.eclipse.team.internal.core.mapping.PathTree; 23 import org.eclipse.team.internal.core.subscribers.DiffTreeStatistics; 24 25 33 public class DiffTree implements IDiffTree { 34 35 39 public static final int START_CLIENT_PROPERTY_RANGE = 1024; 40 41 private ListenerList listeners = new ListenerList(); 42 43 private PathTree pathTree = new PathTree(); 44 45 private ILock lock = Job.getJobManager().newLock(); 46 47 private DiffTreeStatistics statistics = new DiffTreeStatistics(); 48 49 private DiffChangeEvent changes; 50 51 private boolean lockedForModification; 52 53 private Map propertyChanges = new HashMap(); 54 55 58 public DiffTree() { 59 resetChanges(); 60 } 61 62 65 public void addDiffChangeListener(IDiffChangeListener listener) { 66 listeners.add(listener); 67 } 68 69 72 public void removeDiffChangeListener(IDiffChangeListener listener) { 73 listeners.remove(listener); 74 } 75 76 79 public void accept(IPath path, IDiffVisitor visitor, int depth) { 80 IDiff delta = getDiff(path); 81 if (delta == null || visitor.visit(delta)) { 82 if (depth == IResource.DEPTH_ZERO) 83 return; 84 IPath[] children = getChildren(path); 85 for (int i = 0; i < children.length; i++) { 86 IPath child = children[i]; 87 accept(child, visitor, depth == IResource.DEPTH_ONE ? IResource.DEPTH_ZERO : IResource.DEPTH_INFINITE); 88 } 89 } 90 } 91 92 95 public IDiff getDiff(IPath path) { 96 return (IDiff)pathTree.get(path); 97 } 98 99 102 public IPath[] getChildren(IPath path) { 103 return pathTree.getChildren(path); 104 } 105 106 109 public boolean isEmpty() { 110 return pathTree.isEmpty(); 111 } 112 113 128 public void add(IDiff delta) { 129 try { 130 beginInput(); 131 IDiff oldDiff = getDiff(delta.getPath()); 132 internalAdd(delta); 133 if (oldDiff != null) { 134 internalChanged(delta); 135 } else { 136 internalAdded(delta); 137 } 138 } finally { 139 endInput(null); 140 } 141 } 142 143 159 public void remove(IPath path) { 160 try { 161 beginInput(); 162 IDiff delta = getDiff(path); 163 if (delta != null) { 164 internalRemove(delta); 165 internalRemoved(path, delta); 166 } 167 } finally { 168 endInput(null); 169 } 170 } 171 172 175 public void clear() { 176 try { 177 beginInput(); 178 pathTree.clear(); 179 statistics.clear(); 180 internalReset(); 181 } finally { 182 endInput(null); 183 } 184 } 185 186 206 public void beginInput() { 207 lock.acquire(); 208 } 209 210 217 public void endInput(IProgressMonitor monitor) { 218 try { 219 if (lock.getDepth() == 1) { 220 fireChanges(Policy.monitorFor(monitor)); 223 } 224 } finally { 225 lock.release(); 226 } 227 } 228 229 private void fireChanges(final IProgressMonitor monitor) { 230 231 final DiffChangeEvent event = getChangeEvent(); 232 resetChanges(); 233 final Map propertyChanges = this.propertyChanges; 234 this.propertyChanges = new HashMap(); 235 236 if(event.isEmpty() && ! event.isReset() && propertyChanges.isEmpty()) return; 237 Object [] listeners = this.listeners.getListeners(); 238 for (int i = 0; i < listeners.length; i++) { 239 final IDiffChangeListener listener = (IDiffChangeListener)listeners[i]; 240 SafeRunner.run(new ISafeRunnable() { 241 public void handleException(Throwable exception) { 242 } 244 public void run() throws Exception { 245 try { 246 lockedForModification = true; 247 if (!event.isEmpty() || event.isReset()) 248 listener.diffsChanged(event, Policy.subMonitorFor(monitor, 100)); 249 for (Iterator iter = propertyChanges.keySet().iterator(); iter.hasNext();) { 250 Integer key = (Integer ) iter.next(); 251 Set paths = (Set)propertyChanges.get(key); 252 listener.propertyChanged(DiffTree.this, key.intValue(), (IPath[]) paths.toArray(new IPath[paths 253 .size()])); 254 } 255 256 } finally { 257 lockedForModification = false; 258 } 259 } 260 }); 261 } 262 monitor.done(); 263 } 264 265 private DiffChangeEvent getChangeEvent() { 266 return changes; 267 } 268 269 private void resetChanges() { 270 changes = createEmptyChangeEvent(); 271 } 272 273 private DiffChangeEvent createEmptyChangeEvent() { 274 return new DiffChangeEvent(this); 275 } 276 277 private void internalAdd(IDiff delta) { 278 Assert.isTrue(!lockedForModification); 279 IDiff oldDiff = (IDiff)pathTree.get(delta.getPath()); 280 pathTree.put(delta.getPath(), delta); 281 if(oldDiff == null) { 282 statistics.add(delta); 283 } else { 284 statistics.remove(oldDiff); 285 statistics.add(delta); 286 } 287 boolean isConflict = false; 288 if (delta instanceof IThreeWayDiff) { 289 IThreeWayDiff twd = (IThreeWayDiff) delta; 290 isConflict = twd.getDirection() == IThreeWayDiff.CONFLICTING; 291 } 292 setPropertyToRoot(delta, P_HAS_DESCENDANT_CONFLICTS, isConflict); 293 } 294 295 private void internalRemove(IDiff delta) { 296 Assert.isTrue(!lockedForModification); 297 statistics.remove(delta); 298 setPropertyToRoot(delta, P_HAS_DESCENDANT_CONFLICTS, false); 299 setPropertyToRoot(delta, P_BUSY_HINT, false); 300 pathTree.remove(delta.getPath()); 301 } 302 303 private void internalAdded(IDiff delta) { 304 changes.added(delta); 305 } 306 307 private void internalChanged(IDiff delta) { 308 changes.changed(delta); 309 } 310 private void internalRemoved(IPath path, IDiff delta) { 311 changes.removed(path, delta); 312 } 313 314 private void internalReset() { 315 changes.reset(); 316 } 317 318 322 public IPath[] getPaths() { 323 return pathTree.getPaths(); 324 } 325 326 330 public IDiff[] getDiffs() { 331 return (IDiff[]) pathTree.values().toArray(new IDiff[pathTree.size()]); 332 } 333 334 337 public long countFor(int state, int mask) { 338 if (state == 0) 339 return size(); 340 return statistics.countFor(state, mask); 341 } 342 343 346 public int size() { 347 return pathTree.size(); 348 } 349 350 353 public void setPropertyToRoot(IDiff node, int property, boolean value) { 354 try { 355 beginInput(); 356 IPath[] paths = pathTree.setPropogatedProperty(node.getPath(), property, value); 357 accumulatePropertyChanges(property, paths); 358 } finally { 359 endInput(null); 360 } 361 } 362 363 private void accumulatePropertyChanges(int property, IPath[] paths) { 364 Integer key = new Integer (property); 365 Set changes = (Set)propertyChanges.get(key); 366 if (changes == null) { 367 changes = new HashSet(); 368 propertyChanges.put(key, changes); 369 } 370 for (int i = 0; i < paths.length; i++) { 371 IPath path = paths[i]; 372 changes.add(path); 373 } 374 } 375 376 379 public boolean getProperty(IPath path, int property) { 380 return pathTree.getProperty(path, property); 381 } 382 383 386 public void setBusy(IDiff[] diffs, IProgressMonitor monitor) { 387 try { 388 beginInput(); 389 for (int i = 0; i < diffs.length; i++) { 390 IDiff node = diffs[i]; 391 setPropertyToRoot(node, P_BUSY_HINT, true); 392 } 393 } finally { 394 endInput(monitor); 395 } 396 } 397 398 401 public void clearBusy(IProgressMonitor monitor) { 402 try { 403 beginInput(); 404 IPath[] paths = pathTree.getPaths(); 405 for (int i = 0; i < paths.length; i++) { 406 IPath path = paths[i]; 407 IPath[] changed = pathTree.setPropogatedProperty(path, P_BUSY_HINT, false); 408 accumulatePropertyChanges(P_BUSY_HINT, changed); 409 } 410 } finally { 411 endInput(monitor); 412 } 413 } 414 415 418 public boolean hasMatchingDiffs(IPath path, final FastDiffFilter filter) { 419 final RuntimeException found = new RuntimeException (); 420 try { 421 accept(path, new IDiffVisitor() { 422 public boolean visit(IDiff delta) { 423 if (filter.select(delta)) { 424 throw found; 425 } 426 return false; 427 } 428 429 }, IResource.DEPTH_INFINITE); 430 } catch (RuntimeException e) { 431 if (e == found) 432 return true; 433 throw e; 434 } 435 return false; 436 } 437 438 447 public void reportError(IStatus status) { 448 try { 449 beginInput(); 450 getChangeEvent().errorOccurred(status); 451 } finally { 452 endInput(null); 453 } 454 } 455 } 456 | Popular Tags |