org.eclipse.buildship.ui.generic.NodeSelection.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.buildship.ui.generic.NodeSelection.java

Source

/*
 * Copyright (c) 2015 the original author or authors.
 * 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:
 *     Etienne Studer & Dont Csiks (Gradle Inc.) - initial API and implementation and initial documentation
 */

package org.eclipse.buildship.ui.generic;

import java.util.List;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;

/**
 * Provides information about a given set of selected nodes.
 */
public final class NodeSelection {

    private static final NodeSelection EMPTY = new NodeSelection(ImmutableList.of());

    private final ImmutableList<?> nodes;

    private NodeSelection(List<?> nodes) {
        this.nodes = ImmutableList.copyOf(nodes);
    }

    public boolean isEmpty() {
        return this.nodes.isEmpty();
    }

    public boolean isSingleSelection() {
        return this.nodes.size() == 1;
    }

    public <T> T getFirstNode(Class<T> expectedType) {
        if (isEmpty()) {
            throw new IllegalStateException("Selection is empty.");
        } else {
            return expectedType.cast(this.nodes.get(0));
        }
    }

    public Object getFirstNode() {
        if (isEmpty()) {
            throw new IllegalStateException("Selection is empty.");
        } else {
            return this.nodes.get(0);
        }
    }

    public ImmutableList<?> getNodes() {
        return this.nodes;
    }

    /**
     * Returns a list of all nodes.
     *
     * @param expectedType the expected type of the nodes
     * @return the list of all nodes
     * @throws ClassCastException thrown if a node is not of the expected type
     */
    public <T> ImmutableList<T> getNodes(final Class<T> expectedType) {
        return FluentIterable.from(this.nodes).transform(new Function<Object, T>() {

            @Override
            public T apply(Object input) {
                return expectedType.cast(input);
            }
        }).toList();
    }

    /**
     * Checks whether all nodes are of the given type.
     *
     * @param expectedType the expected type of the nodes
     * @return {@code true} if all nodes match the type
     */
    public boolean hasAllNodesOfType(Class<?> expectedType) {
        return allMatch(Predicates.instanceOf(expectedType));
    }

    /**
     * Checks whether all nodes of this node selection meet the specified criteria.
     *
     * @param predicate the criteria to match
     * @return {@code true} if all nodes match the criteria
     */
    public boolean allMatch(Predicate<Object> predicate) {
        return FluentIterable.from(this.nodes).allMatch(predicate);
    }

    /**
     * Merges this node selection with the given node selection by removing those nodes that are not
     * part of the new selection and by adding those nodes that are only in the new selection. The
     * merge result is returned as a new {@code NodeSelection} instance, while this node selection
     * is not modified.
     *
     * @param newSelection the node selection to merge with
     * @return a new instance containing the merge result
     */
    public NodeSelection mergeWith(NodeSelection newSelection) {
        // short-circuit if the new selection is empty
        if (newSelection.isEmpty()) {
            return NodeSelection.empty();
        }

        List<Object> result = Lists.newArrayList(this.nodes);

        // remove those nodes that are not in the new selection anymore
        result.retainAll(newSelection.getNodes());

        // add those nodes that are new in the new selection
        ImmutableList<?> newlySelected = removeAll(newSelection.getNodes(), result);
        result.addAll(newlySelected);

        return new NodeSelection(result);
    }

    private ImmutableList<?> removeAll(List<?> toRemoveFrom, final List<?> elementsToRemove) {
        return FluentIterable.from(toRemoveFrom).filter(new Predicate<Object>() {

            @Override
            public boolean apply(Object node) {
                return !elementsToRemove.contains(node);
            }
        }).toList();
    }

    /**
     * Creates a new instance representing the empty selection.
     *
     * @return the new instance
     */
    public static NodeSelection empty() {
        return EMPTY;
    }

    /**
     * Creates a new instance reflecting the given {@link IStructuredSelection} instance.
     *
     * @param selection the selection from which to create the new instance
     * @return the new instance
     */
    public static NodeSelection from(IStructuredSelection selection) {
        return selection.isEmpty() ? empty() : new NodeSelection(selection.toList());
    }

    /**
     * Creates a new instance reflecting the given {@link ISelection} instance. All selection
     * sub-types other than the {@link IStructuredSelection} sub-type will always have an empty
     * {@link NodeSelection} instance returned.
     *
     * @param selection the selection from which to create the new instance
     * @return the new instance
     */
    public static NodeSelection from(ISelection selection) {
        return selection instanceof IStructuredSelection ? from((IStructuredSelection) selection) : empty();
    }

}