1 11 package org.eclipse.debug.internal.ui.viewers.model; 12 13 import java.io.IOException ; 14 import java.io.StringWriter ; 15 import java.util.ArrayList ; 16 import java.util.HashMap ; 17 import java.util.HashSet ; 18 import java.util.Iterator ; 19 import java.util.LinkedHashMap ; 20 import java.util.List ; 21 import java.util.Map ; 22 import java.util.Set ; 23 import java.util.Map.Entry; 24 25 import org.eclipse.core.runtime.IAdaptable; 26 import org.eclipse.core.runtime.IProgressMonitor; 27 import org.eclipse.core.runtime.ISafeRunnable; 28 import org.eclipse.core.runtime.IStatus; 29 import org.eclipse.core.runtime.ListenerList; 30 import org.eclipse.core.runtime.Platform; 31 import org.eclipse.core.runtime.PlatformObject; 32 import org.eclipse.core.runtime.SafeRunner; 33 import org.eclipse.core.runtime.Status; 34 import org.eclipse.core.runtime.jobs.Job; 35 import org.eclipse.debug.core.IRequest; 36 import org.eclipse.debug.internal.ui.DebugUIPlugin; 37 import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; 38 import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; 39 import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; 40 import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; 41 import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; 42 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener; 43 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; 44 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor; 45 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; 46 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; 47 import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; 48 import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; 49 import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener; 50 import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; 51 import org.eclipse.debug.internal.ui.views.launch.DebugElementAdapterFactory; 52 import org.eclipse.jface.viewers.IContentProvider; 53 import org.eclipse.jface.viewers.StructuredViewer; 54 import org.eclipse.jface.viewers.TreePath; 55 import org.eclipse.jface.viewers.Viewer; 56 import org.eclipse.jface.viewers.ViewerFilter; 57 import org.eclipse.ui.IMemento; 58 import org.eclipse.ui.XMLMemento; 59 import org.eclipse.ui.progress.UIJob; 60 import org.eclipse.ui.progress.WorkbenchJob; 61 62 67 abstract class ModelContentProvider implements IContentProvider, IModelChangedListener { 68 69 private Viewer fViewer; 70 71 private Map fModelProxies = new HashMap (); 73 76 private FilterTransform fTransform = new FilterTransform(); 77 78 81 private ListenerList fModelListeners = new ListenerList(); 82 83 86 private ListenerList fUpdateListeners = new ListenerList(); 87 88 91 private Map fRequestsInProgress = new HashMap (); 92 93 97 private Map fWaitingRequests = new HashMap (); 98 99 102 private Map fViewerStates = new LRUMap(20); 103 104 107 private ModelDelta fPendingState = null; 108 109 112 private Set fPendingStateSaves = new HashSet (); 113 114 117 private Object fQueuedRestore = null; 118 119 122 class CheckState implements IModelDeltaVisitor { 123 private boolean complete = true; 124 private IModelDelta topDelta = null; 125 128 public boolean visit(IModelDelta delta, int depth) { 129 if (delta.getFlags() != IModelDelta.NO_CHANGE) { 130 if (delta.getFlags() == IModelDelta.REVEAL && !(delta.getElement() instanceof IMemento)) { 131 topDelta = delta; 132 } else { 133 complete = false; 134 return false; 135 } 136 } 137 return true; 138 } 139 140 public boolean isComplete() { 141 return complete; 142 } 143 144 public IModelDelta getTopItemDelta() { 145 return topDelta; 146 } 147 } 148 149 152 class LRUMap extends LinkedHashMap { 153 private static final long serialVersionUID= 1L; 154 private int fMaxSize; 155 LRUMap(int maxSize) { 156 super(); 157 fMaxSize = maxSize; 158 } 159 protected boolean removeEldestEntry(Entry eldest) { 160 return size() > fMaxSize; 161 } 162 } 163 164 167 static final int UPDATE_SEQUENCE_BEGINS = 0; 168 static final int UPDATE_SEQUENCE_COMPLETE = 1; 169 static final int UPDATE_BEGINS = 2; 170 static final int UPDATE_COMPLETE = 3; 171 172 175 protected static final TreePath EMPTY_TREE_PATH = new TreePath(new Object []{}); 176 177 public static boolean DEBUG_CONTENT_PROVIDER = false; 179 public static boolean DEBUG_UPDATE_SEQUENCE = false; 180 181 static { 182 DEBUG_CONTENT_PROVIDER = DebugUIPlugin.DEBUG && "true".equals( Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/contentProvider")); DEBUG_UPDATE_SEQUENCE = DebugUIPlugin.DEBUG && "true".equals( Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/updateSequence")); } 187 188 193 public synchronized void dispose() { 194 synchronized (fRequestsInProgress) { 196 Iterator iterator = fRequestsInProgress.values().iterator(); 197 while (iterator.hasNext()) { 198 List requests = (List ) iterator.next(); 199 Iterator reqIter = requests.iterator(); 200 while (reqIter.hasNext()) { 201 ((IRequest) reqIter.next()).cancel(); 202 } 203 } 204 fWaitingRequests.clear(); 205 } 206 fModelListeners.clear(); 207 fUpdateListeners.clear(); 208 disposeAllModelProxies(); 209 fViewer = null; 210 } 211 212 public synchronized boolean isDisposed() { 213 return fViewer == null; 214 } 215 216 222 public synchronized void inputChanged(Viewer viewer, Object oldInput, Object newInput) { 223 fViewer = viewer; 224 if (oldInput != null) { 225 saveViewerState(oldInput); 226 } 227 if (newInput != oldInput) { 228 disposeAllModelProxies(); 229 fTransform.clear(); 230 if (newInput != null) { 231 installModelProxy(newInput); 232 restoreViewerState(newInput); 233 } 234 } 235 } 236 237 242 protected synchronized void restoreViewerState(final Object input) { 243 fPendingState = null; 244 if (isSavingState()) { 245 fQueuedRestore = input; 246 } else { 247 startRestoreViewerState(input); 248 } 249 } 250 251 256 private synchronized void startRestoreViewerState(final Object input) { 257 fPendingState = null; 258 final IElementMementoProvider defaultProvider = getViewerStateAdapter(input); 259 if (defaultProvider != null) { 260 final ModelDelta delta = new ModelDelta(input, IModelDelta.NO_CHANGE); 262 final XMLMemento inputMemento = XMLMemento.createWriteRoot("VIEWER_INPUT_MEMENTO"); final IMementoManager manager = new IMementoManager() { 264 265 private IElementMementoRequest fRequest; 266 267 270 public synchronized void requestComplete(IElementMementoRequest request) { 271 if (!request.isCanceled() && (request.getStatus() == null || request.getStatus().isOK())) { 272 XMLMemento keyMemento = (XMLMemento) delta.getElement(); 273 StringWriter writer = new StringWriter (); 274 try { 275 keyMemento.save(writer); 276 final ModelDelta stateDelta = (ModelDelta) fViewerStates.remove(writer.toString()); 277 if (stateDelta != null) { 278 if (DEBUG_CONTENT_PROVIDER) { 279 System.out.println("RESTORE: " + stateDelta.toString()); } 281 stateDelta.setElement(input); 282 UIJob job = new UIJob("restore state") { public IStatus runInUIThread(IProgressMonitor monitor) { 285 if (input.equals(getViewer().getInput())) { 286 fPendingState = stateDelta; 287 doInitialRestore(); 288 } 289 return Status.OK_STATUS; 290 } 291 292 }; 293 job.setSystem(true); 294 job.schedule(); 295 } 296 } catch (IOException e) { 297 DebugUIPlugin.log(e); 298 } 299 } 300 } 301 302 305 public void processReqeusts() { 306 defaultProvider.encodeElements(new IElementMementoRequest[]{fRequest}); 307 } 308 309 312 public synchronized void addRequest(IElementMementoRequest req) { 313 fRequest = req; 314 } 315 316 }; 317 manager.addRequest(new ElementMementoRequest(ModelContentProvider.this, manager, getPresentationContext(), 318 delta.getElement(), getViewerTreePath(delta), inputMemento, delta)); 319 manager.processReqeusts(); 320 } 321 } 322 323 326 abstract protected void doInitialRestore(); 327 328 331 abstract void doRestore(final ModelDelta delta); 332 333 338 protected synchronized void doRestore(final TreePath path) { 339 if (fPendingState == null) { 340 return; 341 } 342 final IElementMementoProvider defaultProvider = getViewerStateAdapter(getViewer().getInput()); 343 IModelDeltaVisitor visitor = new IModelDeltaVisitor() { 344 public boolean visit(IModelDelta delta, int depth) { 345 if (delta.getParentDelta() == null) { 346 return true; 347 } 348 Object element = delta.getElement(); 349 Object potentialMatch = path.getSegment(depth - 1); 350 if (element instanceof IMemento) { 351 if (defaultProvider != null) { 352 defaultProvider.compareElements(new IElementCompareRequest[]{ 353 new ElementCompareRequest(ModelContentProvider.this, 354 potentialMatch, path, (IMemento) element, (ModelDelta)delta)}); 355 } 356 } else { 357 if (element.equals(potentialMatch)) { 358 return path.getSegmentCount() > depth; 360 } 361 } 362 return false; 363 } 364 }; 365 fPendingState.accept(visitor); 366 } 367 368 373 protected void saveViewerState(Object input) { 374 IElementMementoProvider stateProvider = getViewerStateAdapter(input); 375 if (stateProvider != null) { 376 ModelDelta delta = new ModelDelta(input, IModelDelta.NO_CHANGE); 378 buildViewerState(delta); 379 if (delta.getChildDeltas().length > 0) { 380 encodeDelta(delta, stateProvider); 382 } 383 } 384 } 385 386 392 protected void encodeDelta(final ModelDelta rootDelta, final IElementMementoProvider defaultProvider) { 393 final XMLMemento inputMemento = XMLMemento.createWriteRoot("VIEWER_INPUT_MEMENTO"); final XMLMemento childrenMemento = XMLMemento.createWriteRoot("CHILDREN_MEMENTO"); final IMementoManager manager = new IMementoManager() { 396 397 400 private List requests = new ArrayList (); 401 private boolean abort = false; 402 403 406 public synchronized void requestComplete(IElementMementoRequest request) { 407 if (!abort) { 408 if (!request.isCanceled() && (request.getStatus() == null || request.getStatus().isOK())) { 409 requests.remove(request); 410 if (requests.isEmpty()) { 411 XMLMemento keyMemento = (XMLMemento) rootDelta.getElement(); 412 StringWriter writer = new StringWriter (); 413 try { 414 keyMemento.save(writer); 415 fViewerStates.put(writer.toString(), rootDelta); 416 } catch (IOException e) { 417 DebugUIPlugin.log(e); 418 } 419 stateSaveComplete(this); 420 } 421 } else { 422 abort = true; 423 Iterator iterator = requests.iterator(); 424 while (iterator.hasNext()) { 425 IElementMementoRequest req = (IElementMementoRequest) iterator.next(); 426 req.cancel(); 427 } 428 requests.clear(); 429 stateSaveComplete(this); 430 } 431 } 432 } 433 434 437 public synchronized void processReqeusts() { 438 defaultProvider.encodeElements((IElementMementoRequest[]) requests.toArray(new IElementMementoRequest[requests.size()])); 439 } 440 441 444 public synchronized void addRequest(IElementMementoRequest request) { 445 requests.add(request); 446 } 447 448 }; 449 IModelDeltaVisitor visitor = new IModelDeltaVisitor() { 450 public boolean visit(IModelDelta delta, int depth) { 451 if (delta.getParentDelta() == null) { 452 manager.addRequest( 453 new ElementMementoRequest(ModelContentProvider.this, manager, getPresentationContext(), 454 delta.getElement(), getViewerTreePath(delta), inputMemento, (ModelDelta)delta)); 455 } else { 456 manager.addRequest( 457 new ElementMementoRequest(ModelContentProvider.this, manager, getPresentationContext(), 458 delta.getElement(), getViewerTreePath(delta), childrenMemento.createChild("CHILD_ELEMENT"), (ModelDelta)delta)); } 460 return true; 461 } 462 }; 463 rootDelta.accept(visitor); 464 stateSaveStarted(manager); 465 manager.processReqeusts(); 466 } 467 468 473 private synchronized void stateSaveStarted(IMementoManager manager) { 474 fPendingStateSaves.add(manager); 475 } 476 477 482 private synchronized void stateSaveComplete(IMementoManager manager) { 483 fPendingStateSaves.remove(manager); 484 if (fQueuedRestore != null) { 485 Object temp = fQueuedRestore; 486 fQueuedRestore = null; 487 restoreViewerState(temp); 488 } 489 } 490 491 496 private synchronized boolean isSavingState() { 497 return !fPendingStateSaves.isEmpty(); 498 } 499 500 505 protected abstract void buildViewerState(ModelDelta delta); 506 507 512 protected synchronized void disposeModelProxy(Object element) { 513 IModelProxy proxy = (IModelProxy) fModelProxies.remove(element); 514 if (proxy != null) { 515 proxy.dispose(); 516 } 517 } 518 519 522 protected synchronized void disposeAllModelProxies() { 523 Iterator updatePolicies = fModelProxies.values().iterator(); 524 while (updatePolicies.hasNext()) { 525 IModelProxy proxy = (IModelProxy) updatePolicies.next(); 526 proxy.dispose(); 527 } 528 fModelProxies.clear(); 529 } 530 531 538 protected synchronized void installModelProxy(Object element) { 539 if (!fModelProxies.containsKey(element)) { 540 IModelProxyFactory modelProxyFactory = getModelProxyFactoryAdapter(element); 541 if (modelProxyFactory != null) { 542 final IModelProxy proxy = modelProxyFactory.createModelProxy( 543 element, getPresentationContext()); 544 if (proxy != null) { 545 fModelProxies.put(element, proxy); 546 Job job = new Job("Model Proxy installed notification job") { protected IStatus run(IProgressMonitor monitor) { 548 if (!monitor.isCanceled()) { 549 proxy.init(getPresentationContext()); 550 Object [] mcls = fModelListeners.getListeners(); 551 for (int i = 0; i < mcls.length; i++) { 552 proxy.addModelChangedListener((IModelChangedListener) mcls[i]); 553 } 554 proxy 555 .addModelChangedListener(ModelContentProvider.this); 556 proxy.installed(getViewer()); 557 } 558 return Status.OK_STATUS; 559 } 560 }; 561 job.setSystem(true); 562 job.schedule(); 563 } 564 } 565 } 566 } 567 568 576 protected IModelProxyFactory getModelProxyFactoryAdapter(Object element) { 577 IModelProxyFactory adapter = null; 578 if (element instanceof IModelProxyFactory) { 579 adapter = (IModelProxyFactory) element; 580 } else if (element instanceof IAdaptable) { 581 IAdaptable adaptable = (IAdaptable) element; 582 adapter = (IModelProxyFactory) adaptable.getAdapter(IModelProxyFactory.class); 583 if (adapter == null && !(element instanceof PlatformObject)) { 584 adapter = (IModelProxyFactory) new DebugElementAdapterFactory().getAdapter(element, IModelProxyFactory.class); 587 } 588 } 589 return adapter; 590 } 591 592 600 protected IElementMementoProvider getViewerStateAdapter(Object element) { 601 IElementMementoProvider adapter = null; 602 if (element instanceof IElementMementoProvider) { 603 adapter = (IElementMementoProvider) element; 604 } else if (element instanceof IAdaptable) { 605 IAdaptable adaptable = (IAdaptable) element; 606 adapter = (IElementMementoProvider) adaptable.getAdapter(IElementMementoProvider.class); 607 } 608 return adapter; 609 } 610 611 616 protected abstract IPresentationContext getPresentationContext(); 617 618 623 public void modelChanged(final IModelDelta delta, final IModelProxy proxy) { 624 WorkbenchJob job = new WorkbenchJob("process model delta") { public IStatus runInUIThread(IProgressMonitor monitor) { 626 if (!proxy.isDisposed()) { 627 updateNodes(new IModelDelta[] { delta }); 628 } 629 return Status.OK_STATUS; 630 } 631 }; 632 job.setSystem(true); 633 job.schedule(); 634 635 } 636 637 protected void updateNodes(IModelDelta[] nodes) { 638 for (int i = 0; i < nodes.length; i++) { 639 IModelDelta node = nodes[i]; 640 int flags = node.getFlags(); 641 642 if ((flags & IModelDelta.ADDED) != 0) { 643 handleAdd(node); 644 } 645 if ((flags & IModelDelta.REMOVED) != 0) { 646 handleRemove(node); 647 } 648 if ((flags & IModelDelta.CONTENT) != 0) { 649 handleContent(node); 650 } 651 if ((flags & IModelDelta.EXPAND) != 0) { 652 handleExpand(node); 653 } 654 if ((flags & IModelDelta.COLLAPSE) != 0) { 655 handleCollapse(node); 656 } 657 if ((flags & IModelDelta.SELECT) != 0) { 658 handleSelect(node); 659 } 660 if ((flags & IModelDelta.STATE) != 0) { 661 handleState(node); 662 } 663 if ((flags & IModelDelta.INSERTED) != 0) { 664 handleInsert(node); 665 } 666 if ((flags & IModelDelta.REPLACED) != 0) { 667 handleReplace(node); 668 } 669 if ((flags & IModelDelta.INSTALL) != 0) { 670 handleInstall(node); 671 } 672 if ((flags & IModelDelta.UNINSTALL) != 0) { 673 handleUninstall(node); 674 } 675 if ((flags & IModelDelta.REVEAL) != 0) { 676 handleReveal(node); 677 } 678 updateNodes(node.getChildDeltas()); 679 } 680 } 681 682 690 protected IElementContentProvider getContentAdapter(Object element) { 691 IElementContentProvider adapter = null; 692 if (element instanceof IElementContentProvider) { 693 adapter = (IElementContentProvider) element; 694 } else if (element instanceof IAdaptable) { 695 IAdaptable adaptable = (IAdaptable) element; 696 adapter = (IElementContentProvider) adaptable.getAdapter(IElementContentProvider.class); 697 if (adapter == null && !(element instanceof PlatformObject)) { 698 adapter = (IElementContentProvider) new DebugElementAdapterFactory().getAdapter(element, IElementContentProvider.class); 701 } 702 } 703 return adapter; 704 } 705 706 protected abstract void handleState(IModelDelta delta); 707 708 protected abstract void handleSelect(IModelDelta delta); 709 710 protected abstract void handleExpand(IModelDelta delta); 711 712 protected abstract void handleCollapse(IModelDelta delta); 713 714 protected abstract void handleContent(IModelDelta delta); 715 716 protected abstract void handleRemove(IModelDelta delta); 717 718 protected abstract void handleAdd(IModelDelta delta); 719 720 protected abstract void handleInsert(IModelDelta delta); 721 722 protected abstract void handleReplace(IModelDelta delta); 723 724 protected abstract void handleReveal(IModelDelta delta); 725 726 protected void handleInstall(IModelDelta delta) { 727 installModelProxy(delta.getElement()); 728 } 729 730 protected void handleUninstall(IModelDelta delta) { 731 disposeModelProxy(delta.getElement()); 732 } 733 734 741 protected TreePath getViewerTreePath(IModelDelta node) { 742 ArrayList list = new ArrayList (); 743 IModelDelta parentDelta = node.getParentDelta(); 744 while (parentDelta != null) { 745 list.add(0, node.getElement()); 746 node = parentDelta; 747 parentDelta = node.getParentDelta(); 748 } 749 return new TreePath(list.toArray()); 750 } 751 752 757 protected Viewer getViewer() { 758 return fViewer; 759 } 760 761 769 public int viewToModelIndex(TreePath parentPath, int index) { 770 return fTransform.viewToModelIndex(parentPath, index); 771 } 772 773 781 public int viewToModelCount(TreePath parentPath, int count) { 782 return fTransform.viewToModelCount(parentPath, count); 783 } 784 785 793 protected int modelToViewIndex(TreePath parentPath, int index) { 794 return fTransform.modelToViewIndex(parentPath, index); 795 } 796 797 805 protected int modelToViewChildCount(TreePath parentPath, int count) { 806 return fTransform.modelToViewCount(parentPath, count); 807 } 808 809 819 protected boolean addFilteredIndex(TreePath parentPath, int index, Object element) { 820 return fTransform.addFilteredIndex(parentPath, index, element); 821 } 822 823 830 protected void removeElementFromFilters(TreePath parentPath, int index) { 831 fTransform.removeElementFromFilters(parentPath, index); 832 } 833 834 842 protected boolean removeElementFromFilters(TreePath parentPath, Object element) { 843 return fTransform.removeElementFromFilters(parentPath, element); 844 } 845 846 853 protected void setModelChildCount(TreePath parentPath, int childCount) { 854 fTransform.setModelChildCount(parentPath, childCount); 855 } 856 857 866 protected boolean shouldFilter(Object parentElementOrTreePath, Object element) { 867 ViewerFilter[] filters = ((StructuredViewer)fViewer).getFilters(); 868 if (filters.length > 0) { 869 for (int j = 0; j < filters.length; j++) { 870 if (!(filters[j].select(fViewer, parentElementOrTreePath, element))) { 871 return true; 872 } 873 } 874 } 875 return false; 876 } 877 878 885 protected boolean isFiltered(TreePath parentPath, int index) { 886 return fTransform.isFiltered(parentPath, index); 887 } 888 889 894 protected void unmapPath(TreePath path) { 895 fTransform.clear(path); 897 cancelSubtreeUpdates(path); 898 } 899 900 905 protected int[] getFilteredChildren(TreePath parent) { 906 return fTransform.getFilteredChildren(parent); 907 } 908 909 protected void clearFilteredChild(TreePath parent, int modelIndex) { 910 fTransform.clear(parent, modelIndex); 911 } 912 913 protected void clearFilters(TreePath parent) { 914 fTransform.clear(parent); 915 } 916 917 protected synchronized IModelDelta checkIfRestoreComplete() { 918 if (fPendingState == null) { 919 return null; 920 } 921 CheckState state = new CheckState(); 922 fPendingState.accept(state); 923 if (state.isComplete()) { 924 fPendingState = null; 925 if (DEBUG_CONTENT_PROVIDER) { 926 System.out.println("RESTORE COMPELTE"); } 928 return state.getTopItemDelta(); 929 } 930 return null; 931 } 932 933 void addViewerUpdateListener(IViewerUpdateListener listener) { 934 fUpdateListeners.add(listener); 935 } 936 937 void removeViewerUpdateListener(IViewerUpdateListener listener) { 938 fUpdateListeners.remove(listener); 939 } 940 941 946 void updateStarted(ViewerUpdateMonitor update) { 947 boolean begin = false; 948 synchronized (fRequestsInProgress) { 949 begin = fRequestsInProgress.isEmpty(); 950 List requests = (List ) fRequestsInProgress.get(update.getSchedulingPath()); 951 if (requests == null) { 952 requests = new ArrayList (); 953 fRequestsInProgress.put(update.getSchedulingPath(), requests); 954 } 955 requests.add(update); 956 } 957 if (begin) { 958 if (DEBUG_UPDATE_SEQUENCE) { 959 System.out.println("MODEL SEQUENCE BEGINS"); } 961 notifyUpdate(UPDATE_SEQUENCE_BEGINS, null); 962 } 963 if (DEBUG_UPDATE_SEQUENCE) { 964 System.out.println("\tBEGIN - " + update); } 966 notifyUpdate(UPDATE_BEGINS, update); 967 } 968 969 974 void updateComplete(ViewerUpdateMonitor update) { 975 boolean end = false; 976 synchronized (fRequestsInProgress) { 977 List requests = (List ) fRequestsInProgress.get(update.getSchedulingPath()); 978 if (requests != null) { 979 requests.remove(update); 980 trigger(update); 981 if (requests.isEmpty()) { 982 fRequestsInProgress.remove(update.getSchedulingPath()); 983 } 984 } 985 end = fRequestsInProgress.isEmpty(); 986 } 987 notifyUpdate(UPDATE_COMPLETE, update); 988 if (DEBUG_UPDATE_SEQUENCE) { 989 System.out.println("\tEND - " + update); } 991 if (end) { 992 if (DEBUG_UPDATE_SEQUENCE) { 993 System.out.println("MODEL SEQUENCE ENDS"); } 995 notifyUpdate(UPDATE_SEQUENCE_COMPLETE, null); 996 } 997 } 998 999 protected void notifyUpdate(final int type, final IViewerUpdate update) { 1000 if (!fUpdateListeners.isEmpty()) { 1001 Object [] listeners = fUpdateListeners.getListeners(); 1002 for (int i = 0; i < listeners.length; i++) { 1003 final IViewerUpdateListener listener = (IViewerUpdateListener) listeners[i]; 1004 SafeRunner.run(new ISafeRunnable() { 1005 public void run() throws Exception { 1006 switch (type) { 1007 case UPDATE_SEQUENCE_BEGINS: 1008 listener.viewerUpdatesBegin(); 1009 break; 1010 case UPDATE_SEQUENCE_COMPLETE: 1011 listener.viewerUpdatesComplete(); 1012 break; 1013 case UPDATE_BEGINS: 1014 listener.updateStarted(update); 1015 break; 1016 case UPDATE_COMPLETE: 1017 listener.updateComplete(update); 1018 break; 1019 } 1020 } 1021 public void handleException(Throwable exception) { 1022 DebugUIPlugin.log(exception); 1023 } 1024 }); 1025 } 1026 } 1027 } 1028 1029 protected void cancelSubtreeUpdates(TreePath path) { 1030 synchronized (fRequestsInProgress) { 1031 Iterator iterator = fRequestsInProgress.entrySet().iterator(); 1032 while (iterator.hasNext()) { 1033 Entry entry = (Entry) iterator.next(); 1034 TreePath entryPath = (TreePath) entry.getKey(); 1035 if (entryPath.startsWith(path, null)) { 1036 List requests = (List ) entry.getValue(); 1037 Iterator reqIter = requests.iterator(); 1038 while (reqIter.hasNext()) { 1039 ((IRequest)reqIter.next()).cancel(); 1040 } 1041 } 1042 } 1043 List purge = new ArrayList (); 1044 iterator = fWaitingRequests.keySet().iterator(); 1045 while (iterator.hasNext()) { 1046 TreePath entryPath = (TreePath) iterator.next(); 1047 if (entryPath.startsWith(path, null)) { 1048 purge.add(entryPath); 1049 } 1050 } 1051 iterator = purge.iterator(); 1052 while (iterator.hasNext()) { 1053 fWaitingRequests.remove(iterator.next()); 1054 } 1055 } 1056 } 1057 1058 1065 void schedule(ViewerUpdateMonitor update) { 1066 synchronized (fRequestsInProgress) { 1067 TreePath schedulingPath = update.getSchedulingPath(); 1068 List requests = (List ) fWaitingRequests.get(schedulingPath); 1069 if (requests == null) { 1070 TreePath parentPath = schedulingPath; 1072 while (fRequestsInProgress.get(parentPath) == null) { 1073 parentPath = parentPath.getParentPath(); 1074 if (parentPath == null) { 1075 update.start(); 1077 return; 1078 } 1079 } 1080 requests = new ArrayList (); 1082 requests.add(update); 1083 fWaitingRequests.put(schedulingPath, requests); 1084 } else { 1085 Iterator reqIter = requests.iterator(); 1087 while (reqIter.hasNext()) { 1088 ViewerUpdateMonitor waiting = (ViewerUpdateMonitor) reqIter.next(); 1089 if (waiting.coalesce(update)) { 1090 return; 1092 } 1093 } 1094 requests.add(update); 1096 return; 1097 } 1098 } 1099 } 1100 1101 1108 void trigger(ViewerUpdateMonitor request) { 1109 if (fWaitingRequests.isEmpty()) { 1110 return; 1111 } 1112 TreePath schedulingPath = request.getSchedulingPath(); 1113 List waiting = (List ) fWaitingRequests.get(schedulingPath); 1114 if (waiting == null) { 1115 int length = Integer.MAX_VALUE; 1117 Iterator entries = fWaitingRequests.entrySet().iterator(); 1118 Entry candidate = null; 1119 while (entries.hasNext()) { 1120 Entry entry = (Entry) entries.next(); 1121 TreePath key = (TreePath) entry.getKey(); 1122 if (key.getSegmentCount() < length) { 1123 candidate = entry; 1124 length = key.getSegmentCount(); 1125 } 1126 } 1127 if (candidate != null) { 1128 startHighestPriorityRequest((TreePath) candidate.getKey(), (List ) candidate.getValue()); 1129 } 1130 } else { 1131 startHighestPriorityRequest(schedulingPath, waiting); 1133 } 1134 } 1135 1136 1140 private void startHighestPriorityRequest(TreePath key, List waiting) { 1141 int priority = 4; 1142 ViewerUpdateMonitor next = null; 1143 Iterator requests = waiting.iterator(); 1144 while (requests.hasNext()) { 1145 ViewerUpdateMonitor vu = (ViewerUpdateMonitor) requests.next(); 1146 if (vu.getPriority() < priority) { 1147 next = vu; 1148 priority = next.getPriority(); 1149 } 1150 } 1151 waiting.remove(next); 1152 if (waiting.isEmpty()) { 1153 fWaitingRequests.remove(key); 1154 } 1155 next.start(); 1156 } 1157 1158 1163 void addModelChangedListener(IModelChangedListener listener) { 1164 fModelListeners.add(listener); 1165 Iterator proxies = fModelProxies.values().iterator(); 1166 while (proxies.hasNext()) { 1167 IModelProxy proxy = (IModelProxy) proxies.next(); 1168 proxy.addModelChangedListener(listener); 1169 } 1170 } 1171 1172 1177 void removeModelChangedListener(IModelChangedListener listener) { 1178 fModelListeners.remove(listener); 1179 Iterator proxies = fModelProxies.values().iterator(); 1180 while (proxies.hasNext()) { 1181 IModelProxy proxy = (IModelProxy) proxies.next(); 1182 proxy.removeModelChangedListener(listener); 1183 } 1184 } 1185 1186 1192 protected Object getElement(TreePath path) { 1193 if (path.getSegmentCount() > 0) { 1194 return path.getLastSegment(); 1195 } 1196 return getViewer().getInput(); 1197 } 1198 1199 1207 protected void rescheduleUpdates(TreePath parentPath, int modelIndex) { 1208 synchronized (fRequestsInProgress) { 1209 List requests = (List )fRequestsInProgress.get(parentPath); 1210 List reCreate = null; 1211 if (requests != null) { 1212 Iterator iterator = requests.iterator(); 1213 while (iterator.hasNext()) { 1214 IViewerUpdate update = (IViewerUpdate) iterator.next(); 1215 if (update instanceof IChildrenUpdate) { 1216 IChildrenUpdate childrenUpdate = (IChildrenUpdate) update; 1217 if (childrenUpdate.getOffset() > modelIndex) { 1218 childrenUpdate.cancel(); 1219 if (reCreate == null) { 1220 reCreate = new ArrayList (); 1221 } 1222 reCreate.add(childrenUpdate); 1223 if (DEBUG_CONTENT_PROVIDER) { 1224 System.out.println("canceled update in progress handling REMOVE: " + childrenUpdate); } 1226 } 1227 } 1228 } 1229 } 1230 requests = (List )fWaitingRequests.get(parentPath); 1231 if (requests != null) { 1232 Iterator iterator = requests.iterator(); 1233 while (iterator.hasNext()) { 1234 IViewerUpdate update = (IViewerUpdate) iterator.next(); 1235 if (update instanceof IChildrenUpdate) { 1236 IChildrenUpdate childrenUpdate = (IChildrenUpdate) update; 1237 if (childrenUpdate.getOffset() > modelIndex) { 1238 ((ChildrenUpdate)childrenUpdate).setOffset(childrenUpdate.getOffset() - 1); 1239 if (DEBUG_CONTENT_PROVIDER) { 1240 System.out.println("modified waiting update handling REMOVE: " + childrenUpdate); } 1242 } 1243 } 1244 } 1245 } 1246 if (reCreate != null) { 1250 Iterator iterator = reCreate.iterator(); 1251 while (iterator.hasNext()) { 1252 IChildrenUpdate childrenUpdate = (IChildrenUpdate) iterator.next(); 1253 int start = childrenUpdate.getOffset() - 1; 1254 int end = start + childrenUpdate.getLength(); 1255 for (int i = start; i < end; i++) { 1256 ((TreeModelContentProvider)this).doUpdateElement(parentPath, i); 1257 } 1258 } 1259 } 1260 } 1261 } 1262} 1263 | Popular Tags |