org.eclipse.sirius.diagram.sequence.business.internal.layout.EventEndToPositionFunction.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.sequence.business.internal.layout.EventEndToPositionFunction.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.layout;

import java.util.Collection;
import java.util.Iterator;

import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.AbstractFrame;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.AbstractNodeEvent;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.ISequenceEvent;
import org.eclipse.sirius.diagram.sequence.business.internal.elements.Operand;
import org.eclipse.sirius.diagram.sequence.business.internal.ordering.EventEndHelper;
import org.eclipse.sirius.diagram.sequence.business.internal.query.ISequenceElementQuery;
import org.eclipse.sirius.diagram.sequence.ordering.CompoundEventEnd;
import org.eclipse.sirius.diagram.sequence.ordering.EventEnd;
import org.eclipse.sirius.diagram.sequence.ordering.SingleEventEnd;
import org.eclipse.sirius.diagram.sequence.util.Range;
import org.eclipse.sirius.ext.base.Option;

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

/**
 * Function to compute position of and EventEnd.
 * 
 * @author pcmporhel
 */
public class EventEndToPositionFunction implements Function<EventEnd, Integer> {

    private final Function<EventEnd, Collection<ISequenceEvent>> eventEndToSequenceEvents;

    private final Function<ISequenceEvent, Option<Range>> ranges;

    /**
     * Constructor.
     * 
     * @param eventEndToSequenceEvents
     *            function to get sequence event linked to the given event end.
     * @param ranges
     *            ranges of sequence events.
     */
    public EventEndToPositionFunction(Function<EventEnd, Collection<ISequenceEvent>> eventEndToSequenceEvents,
            Function<ISequenceEvent, Option<Range>> ranges) {
        this.eventEndToSequenceEvents = eventEndToSequenceEvents;
        this.ranges = ranges;
    }

    /**
     * {@inheritDoc}
     */
    public Integer apply(EventEnd from) {
        return getOldPosition(from, eventEndToSequenceEvents.apply(from));
    }

    private Integer getOldPosition(EventEnd end, Collection<ISequenceEvent> ises) {
        SingleEventEnd see = null;
        ISequenceEvent ise = null;
        if (end instanceof SingleEventEnd && !ises.isEmpty()) {
            see = (SingleEventEnd) end;
            ise = ises.iterator().next();
        } else if (end instanceof CompoundEventEnd && !ises.isEmpty()) {
            CompoundEventEnd cee = (CompoundEventEnd) end;
            if (EventEndHelper.PUNCTUAL_COMPOUND_EVENT_END.apply(cee)) {
                ise = getSafeEvent(ises);
            } else {
                ise = getSafeEvent(ises);
                see = ise == null ? null
                        : EventEndHelper.getSingleEventEnd(end,
                                ((DDiagramElement) ise.getNotationView().getElement()).getTarget());
            }
        }
        return getOldPositionFromRange(see, ise);
    }

    private ISequenceEvent getSafeEvent(Collection<ISequenceEvent> ises) {
        ISequenceEvent ise = null;
        Predicate<Object> safe = Predicates.or(Predicates.instanceOf(AbstractNodeEvent.class),
                Predicates.instanceOf(AbstractFrame.class));
        Collection<? extends ISequenceEvent> safeEvents = Lists.newArrayList(Iterables.filter(ises, safe));

        if (!safeEvents.isEmpty()) {
            ise = safeEvents.iterator().next();
        } else if (Iterables.size(Iterables.filter(ises, Operand.class)) == 2) {
            ise = getSafeOperandEnd(ises);
        } else {
            ise = ises.iterator().next();
        }
        return ise;
    }

    private ISequenceEvent getSafeOperandEnd(Collection<ISequenceEvent> ises) {
        ISequenceEvent ise = null;

        Iterator<ISequenceEvent> iterator = ises.iterator();
        ISequenceEvent pot1 = iterator.next();
        ISequenceEvent pot2 = iterator.next();

        if (new ISequenceElementQuery(pot1).hasAbsoluteBoundsFlag()) {
            ise = pot1;
        } else if (new ISequenceElementQuery(pot2).hasAbsoluteBoundsFlag()) {
            ise = pot2;
        }
        return ise;
    }

    /**
     * Get the old position of the corresponding event end, regarding the given
     * event old range. event.
     * 
     * @param see
     *            event end
     * @param ise
     *            corresponding event
     * @return old position
     */
    protected Integer getOldPositionFromRange(SingleEventEnd see, ISequenceEvent ise) {
        Integer oldPosition = 0;
        Option<Range> oldRange = ranges.apply(ise);

        if (ise != null && oldRange.some()) {
            if (see != null) {
                oldPosition = see.isStart() ? oldRange.get().getLowerBound() : oldRange.get().getUpperBound();
            } else if (see == null && ise.isLogicallyInstantaneous()) {
                oldPosition = oldRange.get().middleValue();
            }
        }
        return oldPosition;
    }
}