1 11 package org.eclipse.debug.internal.ui.viewers; 12 13 import java.util.ArrayList ; 14 import java.util.HashMap ; 15 import java.util.Iterator ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 import org.eclipse.core.runtime.CoreException; 20 import org.eclipse.core.runtime.IAdaptable; 21 import org.eclipse.core.runtime.IProgressMonitor; 22 import org.eclipse.core.runtime.IStatus; 23 import org.eclipse.core.runtime.Platform; 24 import org.eclipse.core.runtime.Status; 25 import org.eclipse.core.runtime.jobs.Job; 26 import org.eclipse.debug.internal.ui.DebugUIPlugin; 27 import org.eclipse.debug.internal.ui.elements.adapters.AsynchronousDebugLabelAdapter; 28 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; 29 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; 30 import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; 31 import org.eclipse.debug.internal.ui.viewers.model.provisional.IStatusMonitor; 32 import org.eclipse.debug.internal.ui.viewers.provisional.AsynchronousContentAdapter; 33 import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter; 34 import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter; 35 import org.eclipse.debug.internal.ui.viewers.provisional.IChildrenRequestMonitor; 36 import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor; 37 import org.eclipse.jface.viewers.ViewerFilter; 38 import org.eclipse.jface.viewers.ViewerSorter; 39 40 45 public abstract class AsynchronousModel { 46 47 private ModelNode fRoot; private Map fElementToNodes = new HashMap (); private Map fModelProxies = new HashMap (); private AsynchronousViewer fViewer; private boolean fDisposed = false; 53 public static boolean DEBUG_MODEL = false; 55 56 static { 57 DEBUG_MODEL = DebugUIPlugin.DEBUG && "true".equals( Platform.getDebugOption("org.eclipse.debug.ui/debug/viewers/model")); } 60 61 class EmptyContentAdapter extends AsynchronousContentAdapter { 62 63 66 protected Object [] getChildren(Object parent, IPresentationContext context) throws CoreException { 67 return EMPTY; 68 } 69 70 73 protected boolean hasChildren(Object element, IPresentationContext context) throws CoreException { 74 return false; 75 } 76 77 80 protected boolean supportsPartId(String id) { 81 return true; 82 } 83 } 84 85 protected IAsynchronousContentAdapter fEmptyContentAdapter = new EmptyContentAdapter(); 86 87 90 private List fPendingUpdates = new ArrayList (); 91 92 95 private List fViewerUpdates = new ArrayList (); 96 97 102 public AsynchronousModel(AsynchronousViewer viewer) { 103 fViewer = viewer; 104 if (DEBUG_MODEL) { 105 StringBuffer buffer = new StringBuffer (); 106 buffer.append("MODEL CREATED for: "); buffer.append(fViewer); 108 buffer.append(" ("); buffer.append(this); 110 buffer.append(")"); DebugUIPlugin.debug(buffer.toString()); 112 } 113 } 114 115 121 public void init(Object root) { 122 if (root != null) { 123 fRoot = new ModelNode(null, root); 124 mapElement(root, fRoot); 125 } 126 } 127 128 protected AsynchronousViewer getViewer() { 129 return fViewer; 130 } 131 132 135 public synchronized void dispose() { 136 if (DEBUG_MODEL) { 137 StringBuffer buffer = new StringBuffer (); 138 buffer.append("MODEL DISPOSED for: "); buffer.append(fViewer); 140 buffer.append(" ("); buffer.append(this); 142 buffer.append(")"); DebugUIPlugin.debug(buffer.toString()); 144 } 145 fDisposed = true; 146 cancelPendingUpdates(); 147 disposeAllModelProxies(); 148 ModelNode rootNode = getRootNode(); 149 if (rootNode != null) { 150 rootNode.dispose(); 151 } 152 fElementToNodes.clear(); 153 } 154 155 158 public synchronized boolean isDisposed() { 159 return fDisposed; 160 } 161 162 165 protected synchronized void cancelPendingUpdates() { 166 Iterator updates = fPendingUpdates.iterator(); 167 while (updates.hasNext()) { 168 IStatusMonitor update = (IStatusMonitor) updates.next(); 169 updates.remove(); 170 update.setCanceled(true); 171 } 172 fPendingUpdates.clear(); 173 } 174 175 181 public synchronized void installModelProxy(Object element) { 182 if (!fModelProxies.containsKey(element)) { 183 IModelProxyFactory modelProxyFactory = getModelProxyFactoryAdapter(element); 184 if (modelProxyFactory != null) { 185 final IModelProxy proxy = modelProxyFactory.createModelProxy(element, getPresentationContext()); 186 if (proxy != null) { 187 fModelProxies.put(element, proxy); 188 Job job = new Job("Model Proxy installed notification job") { protected IStatus run(IProgressMonitor monitor) { 190 if (!monitor.isCanceled()) { 191 proxy.init(getPresentationContext()); 192 getViewer().modelProxyAdded(proxy); 193 proxy.installed(getViewer()); 194 } 195 return Status.OK_STATUS; 196 } 197 }; 198 job.setSystem(true); 199 job.schedule(); 200 } 201 } 202 } 203 } 204 205 210 protected synchronized void disposeModelProxy(Object element) { 211 IModelProxy proxy = (IModelProxy) fModelProxies.remove(element); 212 if (proxy != null) { 213 getViewer().modelProxyRemoved(proxy); 214 proxy.dispose(); 215 } 216 } 217 218 221 private void disposeAllModelProxies() { 222 synchronized(fModelProxies) { 223 Iterator updatePolicies = fModelProxies.values().iterator(); 224 while (updatePolicies.hasNext()) { 225 IModelProxy proxy = (IModelProxy)updatePolicies.next(); 226 getViewer().modelProxyRemoved(proxy); 227 proxy.dispose(); 228 } 229 230 fModelProxies.clear(); 231 } 232 } 233 234 239 protected IPresentationContext getPresentationContext() { 240 return fViewer.getPresentationContext(); 241 } 242 243 249 protected IModelProxyFactory getModelProxyFactoryAdapter(Object element) { 250 IModelProxyFactory adapter = null; 251 if (element instanceof IModelProxyFactory) { 252 adapter = (IModelProxyFactory) element; 253 } else if (element instanceof IAdaptable) { 254 IAdaptable adaptable = (IAdaptable) element; 255 adapter = (IModelProxyFactory) adaptable.getAdapter(IModelProxyFactory.class); 256 } 257 return adapter; 258 } 259 260 266 protected synchronized void mapElement(Object element, ModelNode node) { 267 ModelNode[] nodes = getNodes(element); 268 node.remap(element); 269 if (nodes == null) { 270 fElementToNodes.put(element, new ModelNode[] { node}); 271 } else { 272 for (int i = 0; i < nodes.length; i++) { 273 if (nodes[i] == node) { 274 return; 275 } 276 } 277 ModelNode[] old = nodes; 278 ModelNode[] newNodes = new ModelNode[old.length + 1]; 279 System.arraycopy(old, 0, newNodes, 0, old.length); 280 newNodes[old.length] = node; 281 fElementToNodes.put(element, newNodes); 282 } 283 installModelProxy(element); 284 } 285 286 291 protected synchronized void unmapNode(ModelNode node) { 292 Object element = node.getElement(); 293 ModelNode[] nodes = (ModelNode[]) fElementToNodes.get(element); 294 if (nodes == null) { 295 return; 296 } 297 if (nodes.length == 1) { 298 fElementToNodes.remove(element); 299 disposeModelProxy(element); 300 } else { 301 for (int i = 0; i < nodes.length; i++) { 302 ModelNode node2 = nodes[i]; 303 if (node2 == node) { 304 ModelNode[] newNodes= new ModelNode[nodes.length - 1]; 305 System.arraycopy(nodes, 0, newNodes, 0, i); 306 if (i < newNodes.length) { 307 System.arraycopy(nodes, i + 1, newNodes, i, newNodes.length - i); 308 } 309 fElementToNodes.put(element, newNodes); 310 } 311 } 312 } 313 } 314 315 322 public synchronized ModelNode[] getNodes(Object element) { 323 return (ModelNode[]) fElementToNodes.get(element); 324 } 325 326 331 public ModelNode getRootNode() { 332 return fRoot; 333 } 334 335 341 protected void requestScheduled(IStatusMonitor update) { 342 AsynchronousRequestMonitor absUpdate = (AsynchronousRequestMonitor) update; 343 synchronized (fPendingUpdates) { 344 Iterator updates = fPendingUpdates.listIterator(); 345 while (updates.hasNext()) { 346 AsynchronousRequestMonitor pendingUpdate = (AsynchronousRequestMonitor) updates.next(); 347 if (absUpdate.contains(pendingUpdate)) { 348 updates.remove(); 349 pendingUpdate.setCanceled(true); 350 } 351 } 352 fPendingUpdates.add(update); 353 } 354 } 355 356 361 protected void requestComplete(IStatusMonitor update) { 362 synchronized (fPendingUpdates) { 363 fPendingUpdates.remove(update); 364 } 365 } 366 367 372 protected void viewerUpdateScheduled(IStatusMonitor update) { 373 synchronized (fPendingUpdates) { 375 fViewerUpdates.add(update); 376 } 377 } 378 379 387 protected Object [] filter(Object parent, Object [] elements) { 388 ViewerFilter[] filters = getViewer().getFilters(); 389 if (filters != null) { 390 ArrayList filtered = new ArrayList (elements.length); 391 for (int i = 0; i < elements.length; i++) { 392 boolean add = true; 393 for (int j = 0; j < filters.length; j++) { 394 add = filters[j].select(getViewer(), parent, elements[i]); 395 if (!add) 396 break; 397 } 398 if (add) 399 filtered.add(elements[i]); 400 } 401 return filtered.toArray(); 402 } 403 return elements; 404 } 405 406 411 protected void updateLabel(ModelNode node) { 412 Object element = node.getElement(); 413 IAsynchronousLabelAdapter adapter = getLabelAdapter(element); 414 if (adapter != null) { 415 ILabelRequestMonitor labelUpdate = new LabelRequestMonitor(node, this); 416 requestScheduled(labelUpdate); 417 adapter.retrieveLabel(element, getPresentationContext(), labelUpdate); 418 } 419 } 420 421 427 protected IAsynchronousLabelAdapter getLabelAdapter(Object element) { 428 IAsynchronousLabelAdapter adapter = null; 429 if (element instanceof IAsynchronousLabelAdapter) { 430 adapter = (IAsynchronousLabelAdapter) element; 431 } else if (element instanceof IAdaptable) { 432 IAdaptable adaptable = (IAdaptable) element; 433 adapter = (IAsynchronousLabelAdapter) adaptable.getAdapter(IAsynchronousLabelAdapter.class); 434 } 435 if (adapter == null) { 437 return new AsynchronousDebugLabelAdapter(); 438 } 439 return adapter; 440 } 441 442 450 protected IAsynchronousContentAdapter getContentAdapter(Object element) { 451 IAsynchronousContentAdapter adapter = null; 452 if (element instanceof IAsynchronousContentAdapter) { 453 adapter = (IAsynchronousContentAdapter) element; 454 } else if (element instanceof IAdaptable) { 455 IAdaptable adaptable = (IAdaptable) element; 456 adapter = (IAsynchronousContentAdapter) adaptable.getAdapter(IAsynchronousContentAdapter.class); 457 } 458 return adapter; 459 } 460 461 467 public void updateChildren(ModelNode parent) { 468 Object element = parent.getElement(); 469 IAsynchronousContentAdapter adapter = getContentAdapter(element); 470 if (adapter == null) { 471 adapter = fEmptyContentAdapter; 472 } 473 if (adapter != null) { 474 IChildrenRequestMonitor update = new ChildrenRequestMonitor(parent, this); 475 requestScheduled(update); 476 adapter.retrieveChildren(element, getPresentationContext(), update); 477 } 478 } 479 480 485 protected void preservingSelection(Runnable update) { 486 getViewer().preservingSelection(update); 487 } 488 489 494 protected void viewerUpdateComplete(IStatusMonitor monitor) { 495 synchronized (fPendingUpdates) { 497 fViewerUpdates.remove(monitor); 498 } 499 getViewer().updateComplete(monitor); 500 } 501 502 507 protected void requestCanceled(AsynchronousRequestMonitor monitor) { 508 synchronized (fPendingUpdates) { 509 fPendingUpdates.remove(monitor); 510 } 511 } 512 513 518 protected boolean hasPendingUpdates() { 519 synchronized (fViewerUpdates) { 520 return !fPendingUpdates.isEmpty() || !fViewerUpdates.isEmpty(); 521 } 522 } 523 524 530 protected abstract void add(ModelNode parent, Object element); 531 532 538 protected void setChildren(final ModelNode parentNode, List kids) { 539 540 final Object [] children = filter(parentNode.getElement(), kids.toArray()); 541 final AsynchronousViewer viewer = getViewer(); 542 ViewerSorter sorter = viewer.getSorter(); 543 if (sorter != null) { 544 sorter.sort(viewer, children); 545 } 546 547 ModelNode[] prevKids = null; 548 ModelNode[] newChildren = null; 549 ModelNode[] unmap = null; 550 551 synchronized (this) { 552 if (isDisposed()) { 553 return; 554 } 555 prevKids = parentNode.getChildrenNodes(); 556 if (prevKids == null) { 557 newChildren = new ModelNode[children.length]; 558 for (int i = 0; i < children.length; i++) { 559 ModelNode node = new ModelNode(parentNode, children[i]); 560 mapElement(children[i], node); 561 newChildren[i] = node; 562 } 563 parentNode.setChildren(newChildren); 564 } else { 565 newChildren = new ModelNode[children.length]; 566 unmap = new ModelNode[prevKids.length]; 567 for (int i = 0; i < prevKids.length; i++) { 568 unmap[i] = prevKids[i]; 569 } 570 for (int i = 0; i < children.length; i++) { 571 Object child = children[i]; 572 boolean found = false; 573 for (int j = 0; j < prevKids.length; j++) { 574 ModelNode prevKid = prevKids[j]; 575 if (prevKid != null && child.equals(prevKid.getElement())) { 576 newChildren[i] = prevKid; 577 prevKids[j] = null; 578 found = true; 579 break; 580 } 581 } 582 if (!found) { 583 newChildren[i] = new ModelNode(parentNode, child); 584 mapElement(child, newChildren[i]); 585 } 586 } 587 for (int i = 0; i < prevKids.length; i++) { 588 ModelNode kid = prevKids[i]; 589 if (kid != null) { 590 kid.dispose(); 591 unmapNode(kid); 592 } 593 } 594 parentNode.setChildren(newChildren); 595 } 596 if (DEBUG_MODEL) { 597 DebugUIPlugin.debug("CHILDREN CHANGED: " + parentNode); DebugUIPlugin.debug(toString()); 599 } 600 } 601 602 final ModelNode[] finalUnmap = unmap; 604 preservingSelection(new Runnable () { 605 public void run() { 606 if (finalUnmap != null) { 607 for (int i = 0; i < finalUnmap.length; i++) { 608 viewer.unmapNode(finalUnmap[i]); 609 } 610 } 611 viewer.nodeChildrenChanged(parentNode); 612 } 613 }); 614 615 } 616 617 public String toString() { 618 StringBuffer buf = new StringBuffer (); 619 if (fRoot != null) { 620 buf.append("ROOT: "); append(buf, fRoot, 0); 622 } else { 623 buf.append("ROOT: null"); } 625 return buf.toString(); 626 } 627 628 private void append(StringBuffer buf, ModelNode node, int level) { 629 for (int i = 0; i < level; i++) { 630 buf.append('\t'); 631 } 632 buf.append(node); 633 buf.append('\n'); 634 ModelNode[] childrenNodes = node.getChildrenNodes(); 635 if (childrenNodes != null) { 636 for (int i = 0; i < childrenNodes.length; i++) { 637 append(buf, childrenNodes[i], level + 1); 638 } 639 } 640 } 641 } 642 | Popular Tags |