org.eclipse.wst.jsdt.internal.ui.model.JavaSynchronizationContentProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wst.jsdt.internal.ui.model.JavaSynchronizationContentProvider.java

Source

/*******************************************************************************
 * Copyright (c) 2005, 2008 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.jsdt.internal.ui.model;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.resources.mapping.ResourceMappingContext;
import org.eclipse.core.resources.mapping.ResourceTraversal;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptorProxy;
import org.eclipse.ltk.core.refactoring.history.RefactoringHistory;
import org.eclipse.ltk.ui.refactoring.model.AbstractSynchronizationContentProvider;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.team.core.diff.FastDiffFilter;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IDiffChangeEvent;
import org.eclipse.team.core.diff.IDiffTree;
import org.eclipse.team.core.diff.IDiffVisitor;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.core.mapping.ISynchronizationScope;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.ui.navigator.IPipelinedTreeContentProvider;
import org.eclipse.ui.navigator.PipelinedShapeModification;
import org.eclipse.ui.navigator.PipelinedViewerUpdate;
import org.eclipse.wst.jsdt.core.IJavaScriptUnit;
import org.eclipse.wst.jsdt.core.IJavaScriptElement;
import org.eclipse.wst.jsdt.core.IJavaScriptProject;
import org.eclipse.wst.jsdt.core.IPackageFragment;
import org.eclipse.wst.jsdt.core.IPackageFragmentRoot;
import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.internal.corext.util.JavaElementResourceMapping;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;

/**
 * Java-aware synchronization content provider.
 * 
 * 
 */
public final class JavaSynchronizationContentProvider extends AbstractSynchronizationContentProvider
        implements IPipelinedTreeContentProvider {

    /** The refactorings folder */
    //   private static final String NAME_REFACTORING_FOLDER= ".refactorings"; //$NON-NLS-1$

    /**
     * Returns the diffs associated with the element.
     * 
     * @param context
     *            the synchronization context
     * @param element
     *            the element
     * @return an array of diffs
     */
    static IDiff[] getDiffs(final ISynchronizationContext context, final Object element) {
        return context.getDiffTree().getDiffs(getResourceTraversals(element));
    }

    /**
     * Returns the resource mapping for the element.
     * 
     * @param element
     *            the element to get the resource mapping
     * @return the resource mapping
     */
    static ResourceMapping getResourceMapping(final Object element) {
        if (element instanceof IJavaScriptElement)
            return JavaElementResourceMapping.create((IJavaScriptElement) element);
        if (element instanceof IAdaptable) {
            final IAdaptable adaptable = (IAdaptable) element;
            final Object adapted = adaptable.getAdapter(ResourceMapping.class);
            if (adapted instanceof ResourceMapping)
                return (ResourceMapping) adapted;
        }
        return null;
    }

    /**
     * Returns the resource traversals for the element.
     * 
     * @param element
     *            the element to get the resource traversals
     * @return the resource traversals
     */
    static ResourceTraversal[] getResourceTraversals(final Object element) {
        final ResourceMapping mapping = getResourceMapping(element);
        if (mapping != null)
            try {
                return mapping.getTraversals(ResourceMappingContext.LOCAL_CONTEXT, new NullProgressMonitor());
            } catch (final CoreException exception) {
                JavaScriptPlugin.log(exception);
            }
        return new ResourceTraversal[0];
    }

    /** The content provider, or <code>null</code> */
    private ITreeContentProvider fContentProvider = null;

    /** The model root, or <code>null</code> */
    private Object fModelRoot = null;

    /**
     * Returns the java element associated with the project.
     * 
     * @param project
     *            the project
     * @return the associated java element, or <code>null</code> if the
     *         project is not a java project
     */
    private IJavaScriptProject asJavaProject(final IProject project) {
        try {
            if (project.getDescription().hasNature(JavaScriptCore.NATURE_ID))
                return JavaScriptCore.create(project);
        } catch (final CoreException exception) {
            // Only log the error for projects that are accessible (i.e. exist and are open)
            if (project.isAccessible())
                JavaScriptPlugin.log(exception);
        }
        return null;
    }

    /**
     * Converts the shape modification to use java elements.
     * 
     * @param modification
     *            the shape modification to convert
     */
    private void convertToJavaElements(final PipelinedShapeModification modification) {
        final Object parent = modification.getParent();
        if (parent instanceof IResource) {
            final IJavaScriptElement project = asJavaProject(((IResource) parent).getProject());
            if (project != null) {
                modification.getChildren().clear();
                return;
            }
        }
        if (parent instanceof ISynchronizationContext) {
            final Set result = new HashSet();
            for (final Iterator iterator = modification.getChildren().iterator(); iterator.hasNext();) {
                final Object element = iterator.next();
                if (element instanceof IProject) {
                    final IJavaScriptElement project = asJavaProject((IProject) element);
                    if (project != null) {
                        iterator.remove();
                        result.add(project);
                    }
                }
            }
            modification.getChildren().addAll(result);
        }
    }

    /**
     * Converts the viewer update to use java elements.
     * 
     * @param update
     *            the viewer update to convert
     * @return <code>true</code> if any elements have been converted,
     *         <code>false</code> otherwise
     */
    private boolean convertToJavaElements(final PipelinedViewerUpdate update) {
        final Set result = new HashSet();
        for (final Iterator iterator = update.getRefreshTargets().iterator(); iterator.hasNext();) {
            final Object element = iterator.next();
            if (element instanceof IProject) {
                final IJavaScriptElement project = asJavaProject((IProject) element);
                if (project != null) {
                    iterator.remove();
                    result.add(project);
                }
            }
        }
        update.getRefreshTargets().addAll(result);
        return !result.isEmpty();
    }

    /**
     * {@inheritDoc}
     */
    public void diffsChanged(final IDiffChangeEvent event, final IProgressMonitor monitor) {
        syncExec(new Runnable() {

            public void run() {
                handleChange(event);
            }
        }, getViewer().getControl());
    }

    /**
     * Returns all the existing projects that contain additions,
     * removals or deletions.
     * 
     * @param event
     *            the event
     * @return the projects that contain changes
     */
    private IJavaScriptProject[] getChangedProjects(final IDiffChangeEvent event) {
        final Set result = new HashSet();
        final IDiff[] changes = event.getChanges();
        for (int index = 0; index < changes.length; index++) {
            final IResource resource = ResourceDiffTree.getResourceFor(changes[index]);
            if (resource != null) {
                final IJavaScriptProject project = asJavaProject(resource.getProject());
                if (project != null)
                    result.add(project);
            }
        }
        final IDiff[] additions = event.getAdditions();
        for (int index = 0; index < additions.length; index++) {
            final IResource resource = ResourceDiffTree.getResourceFor(additions[index]);
            if (resource != null) {
                final IJavaScriptProject project = asJavaProject(resource.getProject());
                if (project != null)
                    result.add(project);
            }
        }
        final IPath[] removals = event.getRemovals();
        for (int i = 0; i < removals.length; i++) {
            IPath path = removals[i];
            if (path.segmentCount() > 0) {
                IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
                // Only consider projects that still exist
                if (project.exists()) {
                    final IJavaScriptProject javaProject = asJavaProject(project.getProject());
                    if (javaProject != null)
                        result.add(javaProject);
                }
            }
        }
        return (IJavaScriptProject[]) result.toArray(new IJavaScriptProject[result.size()]);
    }

    /**
     * {@inheritDoc}
     */
    protected Object[] getChildrenInContext(final ISynchronizationContext context, final Object parent,
            final Object[] children) {
        final Object[] elements = super.getChildrenInContext(context, parent, children);
        if (parent instanceof IPackageFragment)
            return getPackageFragmentChildren(context, parent, elements);
        else if (parent instanceof IPackageFragmentRoot)
            return getPackageFragmentRootChildren(context, parent, elements);
        else if (parent instanceof IJavaScriptProject)
            return getJavaProjectChildren(context, parent, elements);
        else if (parent instanceof RefactoringHistory)
            return ((RefactoringHistory) parent).getDescriptors();
        // It may be the case that the elements are folders that have a corresponding
        // source folder in which case they should be filtered out
        return getFilteredElements(parent, elements);
    }

    /**
     * Returns the filtered elements.
     * 
     * @param parent
     *            the parent element
     * @param children
     *            the child elements
     * @return the filtered elements
     */
    private Object[] getFilteredElements(final Object parent, final Object[] children) {
        final List result = new ArrayList(children.length);
        for (int index = 0; index < children.length; index++) {
            if (children[index] instanceof IFolder) {
                if (!(JavaScriptCore.create((IFolder) children[index]) instanceof IPackageFragmentRoot))
                    result.add(children[index]);
            } else
                result.add(children[index]);
        }
        return result.toArray();
    }

    /**
     * {@inheritDoc}
     */
    protected ITreeContentProvider getDelegateContentProvider() {
        if (fContentProvider == null)
            fContentProvider = new JavaModelContentProvider();
        return fContentProvider;
    }

    /**
     * Returns the projects that used to have changes in the diff tree 
     * but have been deleted from the workspace.
     * 
     * @param event
     *            the event
     * @return the deleted projects
     */
    private Set getDeletedProjects(final IDiffChangeEvent event) {
        final Set result = new HashSet();
        final IPath[] deletions = event.getRemovals();
        for (int index = 0; index < deletions.length; index++) {
            final IPath path = deletions[index];
            if (path.segmentCount() > 0) {
                IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
                if (!project.isAccessible())
                    result.add(project);
            }
        }
        return result;
    }

    /**
     * Since the this content provider overrides the resource content provider,
     * this method is only invoked when the resource content provider is
     * disabled. In this case, we still want the Java projects to appear at the
     * root of the view.
     * 
     * {@inheritDoc}
     */
    public Object[] getElements(Object parent) {
        if (parent instanceof ISynchronizationContext)
            // Put the resource projects directly under the context
            parent = getModelRoot();
        return super.getElements(parent);
    }

    /**
     * Returns the java project children in the current scope.
     * 
     * @param context
     *            the synchronization context
     * @param parent
     *            the parent element
     * @param children
     *            the child elements
     * @return the java project children
     */
    private Object[] getJavaProjectChildren(final ISynchronizationContext context, final Object parent,
            final Object[] children) {
        final LinkedList list = new LinkedList();
        for (int index = 0; index < children.length; index++) {
            if (children[index] instanceof IPackageFragment) {
                final IPackageFragment fragment = (IPackageFragment) children[index];
                if (getChildren(fragment).length == 0)
                    continue;
            }
            // We need to check whether a folder has non-fragment children (bug 138767)
            if (children[index] instanceof IFolder) {
                IFolder folder = (IFolder) children[index];
                if (getChildren(folder).length == 0)
                    continue;
            }
            list.add(children[index]);
        }

        final IResource resource = JavaModelProvider.getResource(parent);
        if (resource != null) {
            final IResourceDiffTree tree = context.getDiffTree();
            final IResource[] members = tree.members(resource);
            for (int index = 0; index < members.length; index++) {
                IResource child = members[index];
                if (isVisible(context, child)) {
                    if (hasPhantomFolder(tree, child)) {
                        // Add any phantom resources that are visible
                        list.add(child);
                    }

                    //               if (members[index] instanceof IFolder) {
                    //                  final IFolder folder= (IFolder) members[index];
                    //                  if (folder.getName().equals(NAME_REFACTORING_FOLDER)) {
                    //                     final RefactoringHistory history= getRefactorings(context, (IProject) resource, null);
                    //                     if (!history.isEmpty()) {
                    //                        list.remove(folder);
                    //                        list.addFirst(history);
                    //                     }
                    //                  }
                    //               }
                }
            }

        }
        return list.toArray(new Object[list.size()]);
    }

    private boolean hasPhantomFolder(IResourceDiffTree tree, IResource child) {
        if (!child.exists())
            return true;
        final boolean[] found = new boolean[] { false };
        tree.accept(child.getFullPath(), new IDiffVisitor() {
            public boolean visit(IDiff delta) {
                IResource treeResource = ResourceDiffTree.getResourceFor(delta);
                if (treeResource.getType() == IResource.FILE && !treeResource.getParent().exists()) {
                    found[0] = true;
                    return false;
                }

                return true;
            }
        }, IResource.DEPTH_INFINITE);
        return found[0];
    }

    /**
     * {@inheritDoc}
     */
    protected String getModelProviderId() {
        return JavaModelProvider.JAVA_MODEL_PROVIDER_ID;
    }

    /**
     * {@inheritDoc}
     */
    protected Object getModelRoot() {
        if (fModelRoot == null)
            fModelRoot = JavaScriptCore.create(ResourcesPlugin.getWorkspace().getRoot());
        return fModelRoot;
    }

    /**
     * Returns the package fragment children in the current scope.
     * 
     * @param context
     *            the synchronization context
     * @param parent
     *            the parent element
     * @param children
     *            the child elements
     * @return the package fragment children
     */
    private Object[] getPackageFragmentChildren(final ISynchronizationContext context, final Object parent,
            final Object[] children) {
        final Set set = new HashSet();
        for (int index = 0; index < children.length; index++)
            set.add(children[index]);
        final IResource resource = ((IPackageFragment) parent).getResource();
        if (resource != null) {
            final IResourceDiffTree tree = context.getDiffTree();
            final IResource[] members = tree.members(resource);
            for (int index = 0; index < members.length; index++) {
                final int type = members[index].getType();
                if (type == IResource.FILE) {
                    final IDiff diff = tree.getDiff(members[index]);
                    if (diff != null && isVisible(diff))
                        if (isInScope(context.getScope(), parent, members[index])) {
                            final IJavaScriptElement element = JavaScriptCore.create(members[index]);
                            if (element == null) {
                                set.add(members[index]);
                            } else {
                                set.add(element);
                            }
                        }
                }
            }
        }
        return set.toArray(new Object[set.size()]);
    }

    /**
     * Returns the package fragment root children in the current scope.
     * 
     * @param context
     *            the synchronization context
     * @param parent
     *            the parent element
     * @param children
     *            the child elements
     * @return the package fragment root children
     */
    private Object[] getPackageFragmentRootChildren(final ISynchronizationContext context, final Object parent,
            final Object[] children) {
        final Set set = new HashSet();
        for (int index = 0; index < children.length; index++) {
            if (children[index] instanceof IPackageFragment) {
                IPackageFragment fragment = (IPackageFragment) children[index];
                if (fragment.isOpen() && getChildren(fragment).length == 0)
                    // Don't add the default package unless it has children
                    continue;
            }
            set.add(children[index]);
        }
        final IResource resource = JavaModelProvider.getResource(parent);
        if (resource != null) {
            final IResourceDiffTree tree = context.getDiffTree();
            final IResource[] members = tree.members(resource);
            for (int index = 0; index < members.length; index++) {
                final int type = members[index].getType();
                final boolean contained = isInScope(context.getScope(), parent, members[index]);
                final boolean visible = isVisible(context, members[index]);
                if (type == IResource.FILE && contained && visible) {
                    // If the file is not a compilation unit add it.
                    // (compilation units are always children of packages so they
                    // don't need to be added here)
                    final IJavaScriptElement element = JavaScriptCore.create((IFile) members[index]);
                    if (element == null)
                        set.add(members[index]);
                } else if (type == IResource.FOLDER && contained && visible
                        && tree.getDiff(members[index]) != null) {
                    // If the folder is out-of-sync, add it
                    final IJavaScriptElement element = JavaScriptCore.create(members[index]);
                    if (element != null)
                        set.add(element);
                }
                if (type == IResource.FOLDER) {
                    // If the folder contains java elements, add it
                    final IFolder folder = (IFolder) members[index];
                    tree.accept(folder.getFullPath(), new IDiffVisitor() {

                        public final boolean visit(final IDiff diff) {
                            if (isVisible(diff)) {
                                final IResource current = tree.getResource(diff);
                                if (current != null) {
                                    final int kind = current.getType();
                                    if (kind == IResource.FILE) {
                                        final IJavaScriptElement element = JavaScriptCore
                                                .create(current.getParent());
                                        if (element != null)
                                            set.add(element);
                                    } else {
                                        final IJavaScriptElement element = JavaScriptCore.create(current);
                                        if (element != null)
                                            set.add(element);
                                    }
                                }
                            }
                            return true;
                        }
                    }, IResource.DEPTH_INFINITE);
                }
            }
            return set.toArray(new Object[set.size()]);
        }
        return children;
    }

    /**
     * {@inheritDoc}
     */
    public void getPipelinedChildren(final Object parent, final Set children) {
        if (parent instanceof ISynchronizationContext) {
            // When a context is the root, the resource content provider returns
            // projects as direct children. We should replace any projects that
            // are Java projects with an IJavaScriptProject
            final Set result = new HashSet(children.size());
            for (final Iterator iterator = children.iterator(); iterator.hasNext();) {
                final Object element = iterator.next();
                if (element instanceof IProject) {
                    final IJavaScriptElement java = asJavaProject((IProject) element);
                    if (java != null) {
                        iterator.remove();
                        result.add(java);
                    }
                }
                if (element instanceof IFolder) {
                    IFolder folder = (IFolder) element;
                    IJavaScriptElement javaElement = JavaScriptCore.create(folder);
                    // If the folder is also a package, don't show it
                    // as a folder since it will be shown as a package
                    if (javaElement instanceof IPackageFragmentRoot) {
                        iterator.remove();
                    }
                }
            }
            children.addAll(result);
        } else if (parent instanceof ISynchronizationScope) {
            // When the root is a scope, we should return the
            // Java model provider so all model providers appear
            // at the root of the viewer.
            children.add(getModelProvider());
        } else if (parent instanceof IFolder) {
            // Remove any children that are also source folders so they
            // don't appear twice
            for (final Iterator iterator = children.iterator(); iterator.hasNext();) {
                final Object element = iterator.next();
                if (element instanceof IFolder) {
                    IFolder folder = (IFolder) element;
                    IJavaScriptElement javaElement = JavaScriptCore.create(folder);
                    if (javaElement instanceof IPackageFragmentRoot) {
                        iterator.remove();
                    }
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public void getPipelinedElements(final Object element, final Set elements) {
        getPipelinedChildren(element, elements);
    }

    /**
     * {@inheritDoc}
     */
    public Object getPipelinedParent(final Object element, final Object parent) {
        if (element instanceof IJavaScriptElement)
            return getParent(element);
        return parent;
    }

    /**
     * {@inheritDoc}
     */
    protected ResourceTraversal[] getTraversals(final ISynchronizationContext context, final Object object) {
        return getResourceTraversals(object);
    }

    /**
     * Returns the visible projects.
     * 
     * @return the visible projects
     */
    private Set getVisibleProjects() {
        final TreeItem[] children = ((TreeViewer) getViewer()).getTree().getItems();
        final Set result = new HashSet();
        for (int index = 0; index < children.length; index++) {
            final Object data = children[index].getData();
            if (data instanceof IJavaScriptProject)
                result.add(data);
        }
        return result;
    }

    /**
     * Handles a diff change event.
     * 
     * @param event
     *            the event
     */
    private void handleChange(final IDiffChangeEvent event) {
        final Set existing = getVisibleProjects();
        // Get all existing and open projects that contain changes
        // and determine what needs to be done to the project
        // (i.e. add, remove or refresh)
        final IJavaScriptProject[] changed = getChangedProjects(event);
        final List refreshes = new ArrayList(changed.length);
        final List additions = new ArrayList(changed.length);
        final List removals = new ArrayList(changed.length);
        for (int index = 0; index < changed.length; index++) {
            final IJavaScriptProject project = changed[index];
            if (hasVisibleChanges(event.getTree(), project)) {
                if (existing.contains(project))
                    refreshes.add(project);
                else
                    additions.add(project);
            } else
                removals.add(project);
        }
        // Remove any java projects that correspond to deleted or closed projects
        final Set removed = getDeletedProjects(event);
        for (final Iterator iterator = existing.iterator(); iterator.hasNext();) {
            final IJavaScriptProject element = (IJavaScriptProject) iterator.next();
            if (removed.contains(element.getResource()))
                removals.add(element);
        }

        if (!removals.isEmpty() || !additions.isEmpty() || !refreshes.isEmpty()) {
            final TreeViewer viewer = (TreeViewer) getViewer();
            final Tree tree = viewer.getTree();
            try {
                tree.setRedraw(false);
                if (!additions.isEmpty())
                    viewer.add(viewer.getInput(), additions.toArray());
                if (!removals.isEmpty())
                    viewer.remove(viewer.getInput(), removals.toArray());
                if (!refreshes.isEmpty()) {
                    for (final Iterator iter = refreshes.iterator(); iter.hasNext();)
                        viewer.refresh(iter.next());
                }
            } finally {
                tree.setRedraw(true);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    public boolean hasChildren(final Object element) {
        if (element instanceof IJavaScriptUnit || element instanceof IFile
                || element instanceof RefactoringDescriptorProxy || element instanceof RefactoringDescriptor)
            return false;
        return super.hasChildren(element);
    }

    /**
     * Returns whether the element has some children in the current scope.
     * 
     * @param scope
     *            the synchronization scope
     * @param element
     *            the element
     * @param resource
     *            the resource
     * @return <code>true</code> if it has some children, <code>false</code>
     *         otherwise
     */
    private boolean hasChildrenInScope(final ISynchronizationScope scope, final Object element,
            final IResource resource) {
        final IResource[] roots = scope.getRoots();
        final IPath path = resource.getFullPath();
        if (element instanceof IPackageFragment) {
            for (int index = 0; index < roots.length; index++)
                if (path.equals(roots[index].getFullPath().removeLastSegments(1)))
                    return true;
            return false;
        }
        for (int index = 0; index < roots.length; index++)
            if (path.isPrefixOf(roots[index].getFullPath()))
                return true;
        return false;
    }

    /**
     * Has the java project visible changes?
     * 
     * @param tree
     *            the diff tree
     * @param project
     *            the java project
     * @return <code>true</code> if it has visible changes, <code>false</code>
     *         otherwise
     */
    private boolean hasVisibleChanges(final IDiffTree tree, final IJavaScriptProject project) {
        return tree.hasMatchingDiffs(project.getResource().getFullPath(), new FastDiffFilter() {

            public boolean select(final IDiff diff) {
                return isVisible(diff);
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    public PipelinedShapeModification interceptAdd(final PipelinedShapeModification modification) {
        convertToJavaElements(modification);
        return modification;
    }

    /**
     * {@inheritDoc}
     */
    public boolean interceptRefresh(final PipelinedViewerUpdate update) {
        return convertToJavaElements(update);
    }

    /**
     * {@inheritDoc}
     */
    public PipelinedShapeModification interceptRemove(final PipelinedShapeModification modification) {
        convertToJavaElements(modification);
        return modification;
    }

    /**
     * {@inheritDoc}
     */
    public boolean interceptUpdate(final PipelinedViewerUpdate anUpdateSynchronization) {
        return convertToJavaElements(anUpdateSynchronization);
    }

    /**
     * {@inheritDoc}
     */
    protected boolean isInScope(final ISynchronizationScope scope, final Object parent, final Object element) {
        final IResource resource = JavaModelProvider.getResource(element);
        if (resource == null)
            return false;
        if (scope.contains(resource))
            return true;
        if (hasChildrenInScope(scope, element, resource))
            return true;
        return false;
    }

    /**
     * Executes the given runnable.
     * 
     * @param runnable
     *            the runnable
     * @param control
     *            the control
     */
    private void syncExec(final Runnable runnable, final Control control) {
        if (control != null && !control.isDisposed())
            control.getDisplay().syncExec(new Runnable() {

                public void run() {
                    if (!control.isDisposed())
                        BusyIndicator.showWhile(control.getDisplay(), runnable);
                }
            });
    }
}