org.cloudsmith.geppetto.pp.dsl.ui.editor.findrefs.ReferenceSearchResultContentProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.cloudsmith.geppetto.pp.dsl.ui.editor.findrefs.ReferenceSearchResultContentProvider.java

Source

/**
 * Copyright (c) 2012 Cloudsmith Inc. and other contributors, as listed below.
 * 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:
 *   itemis AG - intial API and implementation
 *   Cloudsmith
 * 
 */
package org.cloudsmith.geppetto.pp.dsl.ui.editor.findrefs;

import java.util.Iterator;
import java.util.List;

import org.cloudsmith.geppetto.pp.dsl.linking.PPResourceDescription;
import org.cloudsmith.geppetto.pp.dsl.ui.editor.findrefs.PPReferenceSearchResultEvents.Added;
import org.cloudsmith.geppetto.pp.dsl.ui.editor.findrefs.PPReferenceSearchResultEvents.Reset;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.search.ui.ISearchResultListener;
import org.eclipse.search.ui.SearchResultEvent;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IReferenceDescription;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceDescription.Delta;
import org.eclipse.xtext.resource.IResourceDescription.Event;
import org.eclipse.xtext.resource.IResourceDescriptions;
import org.eclipse.xtext.ui.editor.StatefulResourceDescription;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.Inject;

/**
 * @author Jan Koehnlein - Initial contribution and API
 */
public class ReferenceSearchResultContentProvider
        implements ITreeContentProvider, ISearchResultListener, IResourceDescription.Event.Listener {

    private class UIUpdater extends UIJob {

        public UIUpdater() {
            super("PPReferenceSearchViewUpdater");
            setSystem(true);
        }

        @Override
        public IStatus runInUIThread(IProgressMonitor monitor) {
            isUIUpdateScheduled = false;
            List<SearchResultEvent> events;
            synchronized (batchedSearchResultEvents) {
                events = Lists.newArrayList(batchedSearchResultEvents);
                batchedSearchResultEvents.clear();
            }
            SubMonitor progress = SubMonitor.convert(monitor, events.size());
            for (SearchResultEvent event : events) {
                if (event instanceof Added) {
                    addReference(((Added) event).getReferenceDescription(), true);
                } else if (event instanceof Reset) {
                    if (rootNodes != null && !rootNodes.isEmpty()) {
                        synchronized (viewer) {
                            viewer.remove(viewer.getInput(),
                                    Iterables.toArray(rootNodes, ReferenceSearchViewTreeNode.class));
                            rootNodes = null;
                        }
                    }
                }
                progress.worked(1);
            }
            viewer.refresh();
            viewer.expandToLevel(1);
            return Status.OK_STATUS;
        }
    }

    private IResourceDescriptions resourceDescriptions;

    private List<ReferenceSearchViewTreeNode> rootNodes;

    private TreeViewer viewer;

    private List<SearchResultEvent> batchedSearchResultEvents;

    private volatile boolean isUIUpdateScheduled;

    @Inject
    public ReferenceSearchResultContentProvider(IResourceDescriptions resourceDescriptions) {
        batchedSearchResultEvents = Lists.newArrayList();
        this.resourceDescriptions = resourceDescriptions;
        if (resourceDescriptions instanceof PPResourceDescription.Event.Source) {
            ((PPResourceDescription.Event.Source) resourceDescriptions).addListener(this);
        }
    }

    private void addReference(IReferenceDescription referenceDescription, boolean isUpdateViewer) {
        URI containerEObjectURI = referenceDescription.getContainerEObjectURI();

        // IEObjectDescription sourceContainer = referenceDescription.getSourceContainer(); // getContainerEObjectURI();

        // URI containerEObjectURI = sourceContainer == null
        // ? null
        // : sourceContainer.getEObjectURI();

        final URI eObjectURI = (containerEObjectURI == null) ? referenceDescription.getSourceEObjectUri()
                : containerEObjectURI;
        IResourceDescription resourceDescription = resourceDescriptions
                .getResourceDescription(eObjectURI.trimFragment());
        if (resourceDescription != null) {
            ReferenceSearchViewTreeNode resourceNode = resourceNode(resourceDescription, isUpdateViewer);
            ReferenceSearchViewTreeNode referenceNode = null;
            for (IEObjectDescription eObjectDescription : resourceDescription.getExportedObjects()) {
                if (eObjectDescription.getEObjectURI().equals(eObjectURI)) {
                    referenceNode = new ReferenceSearchViewTreeNode(resourceNode, referenceDescription,
                            eObjectDescription);
                    break;
                }
            }
            if (referenceNode == null)
                referenceNode = new ReferenceSearchViewTreeNode(resourceNode, referenceDescription,
                        referenceDescription);
        }
    }

    public void descriptionsChanged(final Event event) {
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                if (rootNodes != null) {
                    for (Delta delta : event.getDeltas()) {
                        if (!(delta.getNew() instanceof StatefulResourceDescription)) {
                            for (Iterator<ReferenceSearchViewTreeNode> i = rootNodes.iterator(); i.hasNext();) {
                                ReferenceSearchViewTreeNode rootNode = i.next();
                                if (((IResourceDescription) rootNode.getDescription()).getURI()
                                        .equals(delta.getUri())) {
                                    if (delta.getNew() == null) {
                                        i.remove();
                                        viewer.remove(rootNode);
                                        break;
                                    }
                                    Iterable<IReferenceDescription> newReferenceDescriptions = delta.getNew()
                                            .getReferenceDescriptions();
                                    List<ReferenceSearchViewTreeNode> removedReferenceNodes = Lists.newArrayList();
                                    for (ReferenceSearchViewTreeNode referenceNode : rootNode.getChildren()) {
                                        final IReferenceDescription refDesc = ((IReferenceDescription) referenceNode
                                                .getDescription());
                                        final URI referenceSourceURI = refDesc.getSourceEObjectUri();
                                        final URI referenceTargetURI = refDesc.getTargetEObjectUri();
                                        if (Iterables.isEmpty(Iterables.filter(newReferenceDescriptions,
                                                new Predicate<IReferenceDescription>() {
                                                    public boolean apply(IReferenceDescription input) {
                                                        return input.getSourceEObjectUri()
                                                                .equals(referenceSourceURI)
                                                                && input.getTargetEObjectUri()
                                                                        .equals(referenceTargetURI);
                                                    }
                                                }))) {
                                            removedReferenceNodes.add(referenceNode);
                                        }
                                    }
                                    for (ReferenceSearchViewTreeNode removedReferenceNode : removedReferenceNodes) {
                                        rootNode.removeChild(removedReferenceNode);
                                    }
                                    if (rootNode.getChildren().isEmpty()) {
                                        i.remove();
                                        viewer.remove(rootNode);
                                        break;
                                    }
                                    viewer.remove(rootNode, Iterables.toArray(removedReferenceNodes,
                                            ReferenceSearchViewTreeNode.class));
                                }
                            }
                        }
                    }
                }
            }
        });
    }

    public void dispose() {
        rootNodes = null;
    }

    public Object[] getChildren(Object parentElement) {
        if (parentElement instanceof ReferenceSearchViewTreeNode) {
            return Iterables.toArray(((ReferenceSearchViewTreeNode) parentElement).getChildren(),
                    ReferenceSearchViewTreeNode.class);
        }
        return null;
    }

    public Object[] getElements(Object inputElement) {
        if (rootNodes == null || rootNodes.isEmpty()) {
            return new Object[0];
        }
        return Iterables.toArray(rootNodes, ReferenceSearchViewTreeNode.class);
    }

    public Object getParent(Object element) {
        if (element instanceof ReferenceSearchViewTreeNode) {
            return ((ReferenceSearchViewTreeNode) element).getParent();
        }
        return null;
    }

    public boolean hasChildren(Object element) {
        if (element instanceof ReferenceSearchViewTreeNode) {
            return !((ReferenceSearchViewTreeNode) element).getChildren().isEmpty();
        }
        return false;
    }

    public void inputChanged(final Viewer viewer, Object oldInput, Object newInput) {
        synchronized (viewer) {
            if (rootNodes != null) {
                rootNodes.clear();
            }
            if (oldInput instanceof PPReferenceSearchResult) {
                ((PPReferenceSearchResult) oldInput).removeListener(this);
            }
            if (newInput instanceof PPReferenceSearchResult && viewer instanceof TreeViewer) {
                ((PPReferenceSearchResult) newInput).addListener(this);
                this.viewer = (TreeViewer) viewer;
                for (IReferenceDescription referenceDescription : ((PPReferenceSearchResult) newInput)
                        .getMatchingReferences()) {
                    addReference(referenceDescription, false);
                }
            }
        }
    }

    private ReferenceSearchViewTreeNode resourceNode(IResourceDescription resourceDescription,
            boolean isUpdateViewer) {
        if (rootNodes == null) {
            rootNodes = Lists.newArrayList();
        }
        for (ReferenceSearchViewTreeNode node : rootNodes) {
            Object nodeDescription = node.getDescription();
            if (nodeDescription instanceof IResourceDescription) {
                if (((IResourceDescription) nodeDescription).getURI().equals(resourceDescription.getURI())) {
                    return node;
                }
            }
        }
        ReferenceSearchViewTreeNode node = new ReferenceSearchViewTreeNode(null, resourceDescription,
                resourceDescription);
        rootNodes.add(node);
        if (isUpdateViewer) {
            viewer.add(viewer.getInput(), node);
        }
        return node;
    }

    public void searchResultChanged(final SearchResultEvent e) {
        synchronized (batchedSearchResultEvents) {
            batchedSearchResultEvents.add(e);
        }
        if (!isUIUpdateScheduled) {
            isUIUpdateScheduled = true;
            new UIUpdater().schedule();
        }
    }
}