org.eclipse.dd.dsf.ui.viewmodel.update.MultiLevelUpdateHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.dd.dsf.ui.viewmodel.update.MultiLevelUpdateHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2008 Wind River Systems, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Wind River Systems - initial API and implementation
 *******************************************************************************/
package org.eclipse.dd.dsf.ui.viewmodel.update;

import java.util.List;
import java.util.Stack;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.ui.viewmodel.IVMModelProxyExtension;
import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate;
import org.eclipse.dd.dsf.ui.viewmodel.VMHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;

@SuppressWarnings("restriction")
class MultiLevelUpdateHandler extends DataRequestMonitor<List<Object>> {

    private static final boolean DEBUG = Boolean
            .parseBoolean(Platform.getDebugOption("org.eclipse.dd.dsf.ui/debug/vm/atomicUpdate")); //$NON-NLS-1$ //;

    private static final class UpdateLevel {
        private final List<Object> fChildren;
        private final TreePath fPath;
        private int fChildIndex;

        private UpdateLevel(TreePath path, List<Object> children) {
            fPath = path;
            fChildren = children;
            fChildIndex = 0;
            assert !isDone();
        }

        private boolean isDone() {
            return fChildIndex == fChildren.size();
        }

        private Object nextChild() {
            if (isDone()) {
                return null;
            }
            return fChildren.get(fChildIndex++);
        }
    }

    private final class DummyLabelUpdate implements ILabelUpdate {
        private final RequestMonitor fMonitor;
        private final Object fData;
        private final TreePath fPath;

        private DummyLabelUpdate(Object data, TreePath path, RequestMonitor rm) {
            fMonitor = rm;
            fData = data;
            fPath = path;
        }

        public Object getElement() {
            return fData;
        }

        public TreePath getElementPath() {
            return fPath.createChildPath(fData);
        }

        public IPresentationContext getPresentationContext() {
            return fPresentationContext;
        }

        public Object getViewerInput() {
            return fViewerInput;
        }

        public void cancel() {
        }

        public IStatus getStatus() {
            return null;
        }

        public boolean isCanceled() {
            return false;
        }

        public void setStatus(IStatus status) {
        }

        public String[] getColumnIds() {
            return fColumns;
        }

        public void setBackground(RGB arg0, int arg1) {
        }

        public void setFontData(FontData arg0, int arg1) {
        }

        public void setForeground(RGB arg0, int arg1) {
        }

        public void setImageDescriptor(ImageDescriptor arg0, int arg1) {
        }

        public void setLabel(String arg0, int arg1) {
        }

        public void done() {
            fMonitor.done();
        }
    }

    private final Executor fExecutor;
    private final IElementContentProvider fContentProvider;
    private final IPresentationContext fPresentationContext;
    private final String[] fColumns;
    private final Viewer fViewer;
    private final Object fViewerInput;
    private final Stack<UpdateLevel> fStack = new Stack<UpdateLevel>();
    private final CountingRequestMonitor fRequestMonitor;

    private int fIndex = 0;
    private TreePath fCurrentPath;
    private int fLowIndex = 0;
    private int fHighIndex = Integer.MAX_VALUE - 1;
    private int fPendingUpdates;

    public MultiLevelUpdateHandler(Executor executor, IVMModelProxyExtension modelProxy,
            IPresentationContext presentationContext, IElementContentProvider contentProvider,
            RequestMonitor parentRequestMonitor) {
        super(executor, null);
        fExecutor = executor;
        fViewer = modelProxy.getViewer();
        fViewerInput = modelProxy.getViewerInput();
        fCurrentPath = modelProxy.getRootPath();
        fPresentationContext = presentationContext;
        fColumns = presentationContext.getColumns();
        fContentProvider = contentProvider;

        fRequestMonitor = new CountingRequestMonitor(fExecutor, parentRequestMonitor);
    }

    void startUpdate() {
        if (DEBUG)
            System.out.println("[MultiLevelUpdateHandler] startUpdate " + fLowIndex + '-' + fHighIndex); //$NON-NLS-1$
        fContentProvider.update(new IChildrenUpdate[] {
                new VMChildrenUpdate(fCurrentPath, fViewerInput, fPresentationContext, -1, -1, this) });
    }

    void setRange(int low, int high) {
        fLowIndex = low;
        fHighIndex = high;
    }

    boolean isDone() {
        return fStack.isEmpty();
    }

    @Override
    public synchronized void done() {
        try {
            fExecutor.execute(new DsfRunnable() {
                public void run() {
                    final List<Object> data = getData();
                    if (data != null && !data.isEmpty()) {
                        if (DEBUG)
                            System.out.println("[MultiLevelUpdateHandler] gotChildUpdate " + data.size()); //$NON-NLS-1$
                        fStack.push(new UpdateLevel(fCurrentPath, data));
                    }
                    processNext();
                }

                @Override
                public String toString() {
                    return "Completed: " + MultiLevelUpdateHandler.this.toString(); //$NON-NLS-1$
                }
            });
        } catch (RejectedExecutionException e) {
            handleRejectedExecutionException();
        }
    }

    protected void processNext() {
        while (true) {
            if (fIndex > fHighIndex) {
                fStack.clear();
            }
            if (fStack.isEmpty()) {
                fRequestMonitor.setDoneCount(fPendingUpdates);
                super.done();
                return;
            }
            UpdateLevel current = fStack.peek();
            assert !current.isDone();

            TreePath path = current.fPath;
            Object data = current.nextChild();
            if (current.isDone()) {
                fStack.pop();
            }
            if (data == null) {
                // consider null children - http://bugs.eclipse.org/250309
                ++fIndex;
                continue;
            }
            path = path.createChildPath(data);

            if (fIndex >= fLowIndex && fIndex <= fHighIndex) {
                if (data instanceof IAdaptable) {
                    IElementLabelProvider labelProvider = (IElementLabelProvider) ((IAdaptable) data)
                            .getAdapter(IElementLabelProvider.class);
                    if (labelProvider != null) {
                        ++fPendingUpdates;
                        if (DEBUG)
                            System.out.println("[MultiLevelUpdateHandler] labelUpdate " + data); //$NON-NLS-1$
                        labelProvider
                                .update(new ILabelUpdate[] { new DummyLabelUpdate(data, path, fRequestMonitor) });
                    }
                }
            }
            fIndex++;
            if (fViewer instanceof TreeViewer) {
                TreeViewer treeViewer = (TreeViewer) fViewer;
                if (treeViewer.getExpandedState(data)) {
                    fCurrentPath = path;
                    if (DEBUG)
                        System.out.println("[MultiLevelUpdateHandler] childrenUpdate " + data); //$NON-NLS-1$
                    fContentProvider.update(new IChildrenUpdate[] {
                            new VMChildrenUpdate(path, fViewerInput, fPresentationContext, -1, -1, this) });
                    return;
                } else if (fIndex >= fLowIndex) {
                    // update also the hasChildren flag
                    ++fPendingUpdates;
                    if (DEBUG)
                        System.out.println("[MultiLevelUpdateHandler] hasChildUpdate " + data); //$NON-NLS-1$
                    fContentProvider.update(new IHasChildrenUpdate[] { new VMHasChildrenUpdate(path, fViewerInput,
                            fPresentationContext, new DataRequestMonitor<Boolean>(fExecutor, fRequestMonitor)) });
                }
            }
        }
    }
}