org.eclipse.sirius.diagram.sequence.ui.business.internal.migration.SequenceDiagramRepresentationsFileMigrationParticipant.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.sirius.diagram.sequence.ui.business.internal.migration.SequenceDiagramRepresentationsFileMigrationParticipant.java

Source

/*******************************************************************************
 * Copyright (c) 2013, 2014 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.ui.business.internal.migration;

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

import org.eclipse.gmf.runtime.notation.Bounds;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.LayoutConstraint;
import org.eclipse.gmf.runtime.notation.Node;
import org.eclipse.sirius.business.api.migration.AbstractRepresentationsFileMigrationParticipant;
import org.eclipse.sirius.diagram.AbsoluteBoundsFilter;
import org.eclipse.sirius.diagram.AbstractDNode;
import org.eclipse.sirius.diagram.CollapseFilter;
import org.eclipse.sirius.diagram.DDiagramElement;
import org.eclipse.sirius.diagram.DEdge;
import org.eclipse.sirius.diagram.DNode;
import org.eclipse.sirius.diagram.DNodeContainer;
import org.eclipse.sirius.diagram.DNodeList;
import org.eclipse.sirius.diagram.DiagramFactory;
import org.eclipse.sirius.diagram.DiagramPackage;
import org.eclipse.sirius.diagram.GraphicalFilter;
import org.eclipse.sirius.diagram.IndirectlyCollapseFilter;
import org.eclipse.sirius.diagram.sequence.SequenceDDiagram;
import org.eclipse.sirius.diagram.sequence.ui.business.internal.diagramtype.SequenceCollapseUpdater;
import org.eclipse.sirius.diagram.ui.business.api.query.DDiagramGraphicalQuery;
import org.eclipse.sirius.diagram.ui.business.api.query.NodeQuery;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNode2EditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNode3EditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNode4EditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeContainer2EditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeContainerEditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeEditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeList2EditPart;
import org.eclipse.sirius.diagram.ui.internal.edit.parts.DNodeListEditPart;
import org.eclipse.sirius.diagram.ui.part.SiriusVisualIDRegistry;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.viewpoint.DAnalysis;
import org.eclipse.sirius.viewpoint.DView;
import org.osgi.framework.Version;

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

/**
 * Migration contribution for sequence diagram part of representations file.
 * 
 * @author mporhel
 */
public class SequenceDiagramRepresentationsFileMigrationParticipant
        extends AbstractRepresentationsFileMigrationParticipant {

    /**
     * Sequence Message flag reset migration version.
     */
    public static final Version MESSAGE_FLAG_MIGRATION_VERSION = new Version("8.1.1"); //$NON-NLS-1$

    /**
     * Sequence GMF bounds migration version.
     */
    public static final Version GMF_BOUNDS_MIGRATION_VERSION = new Version("6.7.0.201302181200"); //$NON-NLS-1$

    private static final Version GMF_BOUNDS_ALREADY_MIGRATED_VERSION = new Version("6.5.3"); //$NON-NLS-1$

    private static final Version GMF_BOUNDS_NOT_MIGRATED_VERSION = new Version("6.6.0"); //$NON-NLS-1$

    /**
     * The latest VP version for this participant.
     */
    private static final Version MIGRATION_VERSION = MESSAGE_FLAG_MIGRATION_VERSION;

    private Predicate<Node> isNode = new IsNode();

    private Predicate<Node> isCollapsedNode = new IsCollapsedNode();

    private Predicate<Node> isDirectlyCollapsedNode = new IsDirectlyCollapsedNode();

    /**
     * {@inheritDoc}
     * 
     * @see org.eclipse.sirius.business.api.migration.IMigrationParticipant#getMigrationVersion()
     */
    public Version getMigrationVersion() {
        return MIGRATION_VERSION;
    }

    /**
     * {@inheritDoc}
     */
    public void postLoad(DAnalysis dAnalysis, Version loadedVersion) {
        super.postLoad(dAnalysis, loadedVersion);

        if (loadedVersion.compareTo(GMF_BOUNDS_MIGRATION_VERSION) < 0) {
            // The 6.5.3 maintenance version already contains the migration,
            // migration should be done for versions in
            // [0.0.0, 6.5.3[ U [6.6.0, 6.7.0[.
            if (loadedVersion.compareTo(GMF_BOUNDS_ALREADY_MIGRATED_VERSION) < 0
                    || loadedVersion.compareTo(GMF_BOUNDS_NOT_MIGRATED_VERSION) >= 0) {
                List<Diagram> sequenceDiagrams = getGMFSequenceDiagrams(dAnalysis);
                if (!sequenceDiagrams.isEmpty()) {
                    migrateGMFBoundsOfCollapsedBorderedNode(sequenceDiagrams);
                }
            }
        }

        if (loadedVersion.compareTo(MESSAGE_FLAG_MIGRATION_VERSION) < 0) {
            List<SequenceDDiagram> sequenceDDiagrams = getSequenceDDiagrams(dAnalysis);
            if (!sequenceDDiagrams.isEmpty()) {
                for (SequenceDDiagram diagram : sequenceDDiagrams) {
                    for (DEdge edge : diagram.getEdges()) {
                        for (AbsoluteBoundsFilter flag : Iterables.filter(edge.getGraphicalFilters(),
                                AbsoluteBoundsFilter.class)) {
                            // Reset default values, x and width are not used
                            // for Message standard layout.
                            // Specific flags set by commands and refresh
                            // extensions (LayoutConstants.TOOL_CREATION_FLAG,
                            // LayoutConstants.TOOL_CREATION_FLAG_FROM_SEMANTIC,
                            // LayoutConstants.EXTERNAL_CHANGE_FLAG) to detect
                            // unsafe situations have been used by the
                            // SequenceLayout triggered by those commands. But
                            // the reset was not done for Message on previous
                            // versions.
                            flag.setX((Integer) DiagramPackage.eINSTANCE.getAbsoluteBoundsFilter_X()
                                    .getDefaultValue());
                            flag.setWidth((Integer) DiagramPackage.eINSTANCE.getAbsoluteBoundsFilter_Width()
                                    .getDefaultValue());
                        }
                    }
                }
            }
        }
    }

    /**
     * Retrieve all GMF diagrams of the {@link DAnalysis}.
     * 
     * @param dAnalysis
     *            The analysis of the resource to migrate
     * @return Sequence GMF diagrams of this {@link DAnalysis}
     */
    protected List<Diagram> getGMFSequenceDiagrams(DAnalysis dAnalysis) {
        List<Diagram> diagrams = new ArrayList<Diagram>();
        for (SequenceDDiagram diagram : getSequenceDDiagrams(dAnalysis)) {
            DDiagramGraphicalQuery query = new DDiagramGraphicalQuery(diagram);
            Option<Diagram> option = query.getAssociatedGMFDiagram();
            if (option.some()) {
                diagrams.add(option.get());
            }
        }
        return diagrams;
    }

    /**
     * Retrieve all {@link SequenceDDiagram} of the {@link DAnalysis}.
     * 
     * @param dAnalysis
     *            The analysis of the resource to migrate
     * @return {@link SequenceDDiagram} diagrams of this {@link DAnalysis}
     */
    protected List<SequenceDDiagram> getSequenceDDiagrams(DAnalysis dAnalysis) {
        List<SequenceDDiagram> diagrams = new ArrayList<SequenceDDiagram>();
        for (DView view : dAnalysis.getOwnedViews()) {
            Iterables.addAll(diagrams, Iterables.filter(view.getOwnedRepresentations(), SequenceDDiagram.class));
        }
        return diagrams;
    }

    private void migrateGMFBoundsOfCollapsedBorderedNode(List<Diagram> sequenceDiagrams) {
        for (Diagram diagram : sequenceDiagrams) {
            // 1-Add new IndirectlyCollapseFilter
            migrateChildrenOfCollapsedNode(diagram);
            // 2-Set width and height of graphical filters of collapsed nodes
            // (directly or not) with GMF size and set GMF bounds.
            Iterator<Node> viewIterator = Iterators.filter(Iterators.filter(diagram.eAllContents(), Node.class),
                    Predicates.and(isNode, isCollapsedNode));
            while (viewIterator.hasNext()) {
                Node node = viewIterator.next();
                DNode dNode = (DNode) node.getElement();

                LayoutConstraint layoutConstraint = node.getLayoutConstraint();
                if (layoutConstraint instanceof Bounds) {
                    Bounds bounds = (Bounds) layoutConstraint;
                    // The GMF node size must be stored in collapse filter (to
                    // can
                    // set this size when this node is expanded).
                    for (GraphicalFilter graphicalFilter : dNode.getGraphicalFilters()) {
                        if (graphicalFilter instanceof CollapseFilter) {
                            ((CollapseFilter) graphicalFilter).setWidth(bounds.getWidth());
                            ((CollapseFilter) graphicalFilter).setHeight(bounds.getHeight());
                        }
                    }
                    // Set new collapsed GMF bounds
                    SequenceCollapseUpdater scbu = new SequenceCollapseUpdater();
                    scbu.collapseBounds(node, dNode);
                }
            }
        }
    }

    /**
     * Add a {@link IndirectlyCollapsedFilter} to the children of CollapsedNode
     * (to retrieve the same behavior as before). The migration of GMF bounds of
     * this indirectly collapsed nodes, if they are bordered nodes, are deal
     * later in method {{@link #migrateGMFBoundsOfBorderedNodes(List)}.
     * 
     * @param diagram
     *            GMF Diagram to migrate.
     */
    private void migrateChildrenOfCollapsedNode(Diagram diagram) {
        List<DDiagramElement> indirectlyCollaspedDDEs = Lists.newArrayList();
        Iterator<Node> viewIterator = Iterators.filter(Iterators.filter(diagram.eAllContents(), Node.class),
                isDirectlyCollapsedNode);
        while (viewIterator.hasNext()) {
            final Node node = viewIterator.next();
            if (node.getElement() instanceof AbstractDNode) {
                AbstractDNode abstractDNode = (AbstractDNode) node.getElement();
                indirectlyCollaspedDDEs.addAll(abstractDNode.getOwnedBorderedNodes());
                if (abstractDNode instanceof DNodeContainer) {
                    DNodeContainer dDiagramElementContainer = (DNodeContainer) abstractDNode;
                    indirectlyCollaspedDDEs.addAll(dDiagramElementContainer.getOwnedDiagramElements());
                } else if (abstractDNode instanceof DNodeList) {
                    DNodeList dNodeList = (DNodeList) abstractDNode;
                    indirectlyCollaspedDDEs.addAll(dNodeList.getOwnedElements());
                }
            }
        }
        for (DDiagramElement indirectlyCollaspedDDE : indirectlyCollaspedDDEs) {
            if (!Iterables.any(indirectlyCollaspedDDE.getGraphicalFilters(),
                    Predicates.instanceOf(IndirectlyCollapseFilter.class))) {
                IndirectlyCollapseFilter indirectlyCollapseFilter = DiagramFactory.eINSTANCE
                        .createIndirectlyCollapseFilter();
                indirectlyCollaspedDDE.getGraphicalFilters().add(indirectlyCollapseFilter);
            }
        }
    }

    /**
     * Predicate that checks that :
     * <UL>
     * <LI>The input is a GMF Node,</LI>
     * <LI>and this Node is a viewpoint node.</LI>
     * </UL>
     */
    private static class IsNode implements Predicate<Node> {
        public boolean apply(Node input) {
            int type = SiriusVisualIDRegistry.getVisualID(input.getType());
            return type == DNodeEditPart.VISUAL_ID || type == DNode2EditPart.VISUAL_ID
                    || type == DNode3EditPart.VISUAL_ID || type == DNode4EditPart.VISUAL_ID;
        }
    }

    /**
     * Predicate that checks that this GMF Node is collapsed (directly or not).
     * 
     * No check is done on the border position of a node because we need to
     * handle ObservationPoints.
     */
    private static class IsCollapsedNode implements Predicate<Node> {
        public boolean apply(Node input) {
            return new NodeQuery(input).isCollapsed();
        }
    }

    /**
     * Predicate that checks that this GMF Node is directly collapsed.
     * 
     * No check is done on the border position of a node because we need to
     * handle ObservationPoints.
     */
    private static class IsDirectlyCollapsedNode implements Predicate<Node> {
        public boolean apply(Node input) {
            boolean apply = false;

            int type = SiriusVisualIDRegistry.getVisualID(input.getType());
            boolean result = type == DNode2EditPart.VISUAL_ID || type == DNode4EditPart.VISUAL_ID;
            result = result || type == DNodeEditPart.VISUAL_ID || type == DNode3EditPart.VISUAL_ID;
            result = result || type == DNodeContainerEditPart.VISUAL_ID
                    || type == DNodeContainer2EditPart.VISUAL_ID;
            result = result || type == DNodeListEditPart.VISUAL_ID || type == DNodeList2EditPart.VISUAL_ID;

            if (result) {
                return new NodeQuery(input).isDirectlyCollapsed();
            }
            return apply;
        }
    }
}