org.eclipse.sirius.diagram.sequence.business.internal.query.ISequenceEventQuery.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.sequence.business.internal.query.ISequenceEventQuery.java

Source

/*******************************************************************************
 * Copyright (c) 2010 THALES GLOBAL SERVICES.
 * 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:
 *    Obeo - initial API and implementation
 *******************************************************************************/
package org.eclipse.sirius.diagram.sequence.business.internal.query;

import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.eclipse.gmf.runtime.notation.Edge;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.Execution;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.ISequenceElementAccessor;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.ISequenceEvent;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.Message;
import org.eclipse.sirius.diagram.sequence.util.Range;
import org.eclipse.sirius.ext.base.Option;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * General queries on {@link ISequenceEvent}s.
 * 
 * @author pcdavid
 */
public class ISequenceEventQuery {
    /**
     * The event to query.
     */
    protected final ISequenceEvent event;

    /**
     * Constructor.
     * 
     * @param event
     *            the event to query.
     */
    public ISequenceEventQuery(ISequenceEvent event) {
        this.event = Preconditions.checkNotNull(event);
    }

    /**
     * Tests whether this event is an ancestor of the specified child event.
     * 
     * @param child
     *            the potential descendant.
     * @return <code>true</code> if <em>this</em> event is identical to the
     *         child, the parent of the child or an indirect ancestor of the
     *         child.
     */
    public boolean isAncestorOrSelf(ISequenceEvent child) {
        ISequenceEvent iSequenceEvent = event;
        final boolean result;
        if (iSequenceEvent == null || child == null) {
            result = false;
        } else if (iSequenceEvent.equals(child)) {
            result = true;
        } else {
            ISequenceEvent parentEvent = child.getParentEvent();
            if (iSequenceEvent.equals(parentEvent)) {
                result = true;
            } else {
                result = parentEvent != null && isAncestorOrSelf(parentEvent);
            }
        }
        return result;
    }

    /**
     * Tests whether this event is a reflective message.
     * 
     * @return <code>true</code> if this event is a reflective message.
     */
    public boolean isReflectiveMessage() {
        return event instanceof Message && ((Message) event).isReflective();
    }

    /**
     * Computes all the descendants of the specified execution, i.e. the
     * recursive transitive closure on getSubEvents().
     * 
     * The current ise is not included.
     * 
     * @return all the proper descendant events of the given sequence event.
     */
    public Set<ISequenceEvent> getAllDescendants() {
        return getAllDescendants(false, ISequenceEvent.ISEQUENCEEVENT_NOTATION_PREDICATE);
    }

    /**
     * Computes all the descendants of the specified execution, i.e. the
     * recursive transitive closure on getSubEvents().
     * 
     * @param includeSelf
     *            whether or not to consider "self" as a descendant.
     * @return all the proper descendant events of the given sequence event.
     */
    public Set<ISequenceEvent> getAllDescendants(boolean includeSelf) {
        return getAllDescendants(includeSelf, ISequenceEvent.ISEQUENCEEVENT_NOTATION_PREDICATE);
    }

    /**
     * Computes all the descendants of the specified execution, i.e. the
     * recursive transitive closure on getSubEvents().
     * 
     * @param includeSelf
     *            whether or not to consider "self" as a descendant.
     * @param predicate
     *            the predicate to select which descendants to include in the
     *            collection.
     * @return all the proper descendant events of the given execution.
     */
    public Set<ISequenceEvent> getAllDescendants(boolean includeSelf, Predicate<? super View> predicate) {
        Set<ISequenceEvent> result = Sets.newHashSet();
        addAllDescendants(predicate, result);
        if (!includeSelf) {
            result.remove(event);
        }
        return result;
    }

    /**
     * Adds all the descendants of the specified edit part which verify the
     * predicate into a collection. Only children edit parts are considered, not
     * source and target connections.
     * 
     * @param predicate
     *            the predicate to select which descendants to include in the
     *            collection.
     * @param parts
     *            the collection in which to add all the descendants of
     *            <code>element</code> which verify the predicate.
     */
    private void addAllDescendants(Predicate<? super View> predicate, Collection<ISequenceEvent> parts) {
        addAllDescendants(event, predicate, parts);
    }

    private void addAllDescendants(ISequenceEvent ise, Predicate<? super View> predicate,
            Collection<ISequenceEvent> parts) {
        View element = ise.getNotationView();
        if (predicate.apply(element)) {
            Option<ISequenceEvent> iSequenceEvent = ISequenceElementAccessor.getISequenceEvent(element);
            if (iSequenceEvent.some()) {
                parts.add(iSequenceEvent.get());
            }
        }
        for (ISequenceEvent childEvent : ise.getSubEvents()) {
            addAllDescendants(childEvent, predicate, parts);
        }
    }

    /**
     * Finds all the executions without duplicates.
     * 
     * @return the found executions found.
     */
    public Collection<Execution> getAllExecutions() {
        return Lists.newArrayList(
                Iterables.filter(getAllDescendants(true, Execution.notationPredicate()), Execution.class));
    }

    /**
     * Finds all the sequence messages whose source or target is the specified
     * element or any of its descendant edit parts, without duplicates.
     * 
     * @return the messages found without duplicates.
     */
    public Set<Message> getAllMessages() {
        Set<Message> allMessages = Sets.newHashSet();
        allMessages.addAll(getAllMessagesFrom());
        allMessages.addAll(getAllMessagesTo());
        return allMessages;
    }

    /**
     * Finds all the sequence messages whose source is the specified element or
     * any of its descendant edit parts.
     * 
     * @return the messages found.
     */
    public List<Message> getAllMessagesFrom() {
        List<Message> messagesParts = Lists.newArrayList();
        addAllMessagesFrom(event.getNotationView(), messagesParts);
        return messagesParts;
    }

    /**
     * Finds all the sequence messages whose target is the specified element or
     * any of its descendant edit parts.
     * 
     * @return the messages found.
     */
    public List<Message> getAllMessagesTo() {
        List<Message> messagesParts = Lists.newArrayList();
        addAllMessagesTo(event.getNotationView(), messagesParts);
        return messagesParts;
    }

    /**
     * Finds all the sequence messages whose target is the specified element or
     * any of its descendant edit parts and add them to a collection.
     * 
     * @param element
     *            the element from which to start the search for messages.
     * @param messages
     *            the collection in which to add the messages.
     */
    private void addAllMessagesTo(View element, Collection<Message> messages) {
        for (Edge connectionPart : Iterables.filter(Iterables.filter(element.getTargetEdges(), Edge.class),
                Message.notationPredicate())) {
            Option<Message> message = ISequenceElementAccessor.getMessage(connectionPart);
            if (message.some()) {
                messages.add(message.get());
            }
        }
        if (element instanceof Message) {
            messages.add((Message) element);
        }
        for (View child : Iterables.filter(element.getChildren(), Node.class)) {
            addAllMessagesFrom(child, messages);
        }
    }

    /**
     * Finds all the sequence messages whose source is the specified element or
     * any of its descendant edit parts and add them to a collection.
     * 
     * @param element
     *            the element from which to start the search for messages.
     * @param messages
     *            the collection in which to add the messages.
     */
    private void addAllMessagesFrom(View element, Collection<Message> messages) {
        for (Edge connectionPart : Iterables.filter(Iterables.filter(element.getSourceEdges(), Edge.class),
                Message.notationPredicate())) {
            Option<Message> message = ISequenceElementAccessor.getMessage(connectionPart);
            if (message.some()) {
                messages.add(message.get());
            }
        }
        if (element instanceof Message) {
            messages.add((Message) element);
        }
        for (View child : Iterables.filter(element.getChildren(), Node.class)) {
            addAllMessagesFrom(child, messages);
        }
    }

    /**
     * Common implementation of
     * {@link ISequenceEventEditPart#getOccupiedRange()}.
     * 
     * @return the maximal range occupied by children of the event.
     */
    public Range getOccupiedRange() {
        Range range = Range.emptyRange();
        for (ISequenceEvent child : event.getSubEvents()) {
            range = range.union(child.getVerticalRange());
        }
        return range;
    }

    /**
     * Return all moved elements from the context.
     * 
     * @return the all moved elements.
     */
    public Set<ISequenceEvent> getAllSequenceEventToMoveWith() {
        Set<ISequenceEvent> entryPoints = Sets.newLinkedHashSet();
        return getAllSequenceEventToMoveWith(entryPoints);
    }

    /**
     * Return all moved elements from the context.
     * 
     * @param additionnalEntryPoints
     *            additionnal entry points.
     * @return the all moved elements.
     */
    public Set<ISequenceEvent> getAllSequenceEventToMoveWith(Collection<ISequenceEvent> additionnalEntryPoints) {
        Set<ISequenceEvent> entryPoints = Sets.newLinkedHashSet();
        entryPoints.add(event);
        entryPoints.addAll(additionnalEntryPoints);

        Set<ISequenceEvent> moved = Sets.newLinkedHashSet();
        for (ISequenceEvent ise : entryPoints) {
            populateMovedElements(ise, moved);
        }
        return moved;
    }

    private void populateMovedElements(ISequenceEvent inspectedElement, Collection<ISequenceEvent> moved) {
        moved.add(inspectedElement);
        for (ISequenceEvent subEvent : Iterables.filter(inspectedElement.getEventsToMoveWith(),
                Predicates.not(Predicates.in(moved)))) {
            populateMovedElements(subEvent, moved);
        }

    }
}