org.tzi.use.gui.views.diagrams.statemachine.TransitionEdge.java Source code

Java tutorial

Introduction

Here is the source code for org.tzi.use.gui.views.diagrams.statemachine.TransitionEdge.java

Source

/*
 * USE - UML based specification environment
 * Copyright (C) 1999-2012 Mark Richters, University of Bremen
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.tzi.use.gui.views.diagrams.statemachine;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.tzi.use.gui.util.PersistHelper;
import org.tzi.use.gui.views.diagrams.DiagramOptions;
import org.tzi.use.gui.views.diagrams.edges.DirectedEdgeFactory;
import org.tzi.use.gui.views.diagrams.edges.DirectedEdgeFactory.ArrowStyle;
import org.tzi.use.gui.views.diagrams.elements.EdgeProperty;
import org.tzi.use.gui.views.diagrams.elements.PlaceableNode;
import org.tzi.use.gui.views.diagrams.elements.edges.EdgeBase;
import org.tzi.use.gui.views.diagrams.util.Direction;
import org.tzi.use.gui.views.diagrams.waypoints.WayPoint;
import org.tzi.use.gui.views.diagrams.waypoints.WayPointType;
import org.tzi.use.uml.mm.statemachines.MProtocolTransition;
import org.tzi.use.uml.mm.statemachines.MTransition;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.google.common.collect.Multimap;

/**
 * @author Lars Hamann
 * 
 */
public class TransitionEdge extends EdgeBase {

    /** 
     *  Transitions with same source and target can be displayed as "merged".
     *  Therefore, we use a set of transitions. 
     **/
    private final List<MTransition> transitions;

    /** 
     *  Transitions with same source and target can be displayed as "merged".
     *  Therefore, we use a set of transition labels. 
     **/
    private List<TransitionLabel> labels;

    /**
     * If this edge is a reflexive edge it can be located at four different
     * positions: NORT_EAST SOUTH_EAST SOUTH_WEST NORTH_WEST
     */
    Direction fReflexivePosition = Direction.NORTH_EAST;

    /**
     * @param source
     * @param target
     * @param edgeName
     * @param diagram
     */
    protected TransitionEdge(MTransition transition, VertexNode source, VertexNode target, String edgeName,
            DiagramOptions diagramOptions, Direction reflexivePosition) {
        super(source, target, edgeName, diagramOptions, false);

        this.transitions = new ArrayList<MTransition>();
        this.transitions.add(transition);
        this.fReflexivePosition = reflexivePosition;
    }

    @Override
    protected void initializeProperties(Multimap<PropertyOwner, EdgeProperty> properties) {
        super.initializeProperties(properties);
        MTransition t = transitions.get(0);
        this.labels = new ArrayList<TransitionLabel>();
        this.labels.add(new TransitionLabel(t.toString(), t.toString(), this, (VertexNode) fSource,
                getSourceWayPoint(), (VertexNode) fTarget, getTargetWayPoint(), fOpt));
        properties.putAll(PropertyOwner.EDGE, this.labels);
    }

    protected String getIdInternal() {
        //FIXME: Make unique
        return "transition::" + fSource.getId() + "::" + fTarget.getId() + "::";
    }

    private void removeLabel(int index) {
        TransitionLabel label = this.labels.get(index);
        label.dispose();

        this.labels.remove(index);
        this.edgeProperties.remove(PropertyOwner.EDGE, label);
    }

    private void addLabel(TransitionLabel label) {
        this.labels.add(label);
        this.firstDraw = true;
        this.edgeProperties.put(PropertyOwner.EDGE, label);
    }

    public void addTransition(MTransition transition) {
        if (this.transitions.add(transition)) {
            TransitionLabel label = new TransitionLabel(
                    transition.toString() + "::label::" + this.labels.size() + 1, transition.toString(), this,
                    (VertexNode) fSource, getSourceWayPoint(), (VertexNode) fTarget, getTargetWayPoint(),
                    this.fOpt);
            addLabel(label);
        }
    }

    /**
     * @param t
     */
    public void removeTransition(MTransition t) {
        int index = this.transitions.indexOf(t);
        if (index > -1) {
            this.transitions.remove(index);
            removeLabel(index);
            // TODO: Re id labels
        }
    }

    public void mergeTransitionEdge(TransitionEdge transitionEdge) {
        for (int i = 0; i < transitionEdge.transitions.size(); ++i) {
            MTransition transition = transitionEdge.transitions.get(i);
            if (this.transitions.add(transition)) {
                TransitionLabel label = transitionEdge.labels.get(i);
                label.mergeTo(this);
                addLabel(label);
            }
        }
    }

    @Override
    protected void onDraw(Graphics2D g) {

        if (this.isSelected()) {
            g.setColor(fOpt.getEDGE_SELECTED_COLOR());
        } else {
            g.setColor(Color.BLACK);
        }

        EdgeProperty n1 = null;
        Point2D p1 = null;

        WayPoint n2 = null;
        Point2D p2 = null;

        // draw all line segments
        if (!fWayPoints.isEmpty()) {
            Iterator<WayPoint> it = fWayPoints.iterator();
            n1 = it.next();

            n1.draw(g);

            while (it.hasNext()) {
                n2 = it.next();
                p1 = n1.getCenter();
                p2 = n2.getCenter();

                // draw nodeOnEdge
                n2.draw(g);

                try {
                    if (n2.getSpecialID() == WayPointType.TARGET) {
                        DirectedEdgeFactory.drawArrow(g, (int) Math.round(p1.getX()), (int) Math.round(p1.getY()),
                                (int) Math.round(p2.getX()), (int) Math.round(p2.getY()), ArrowStyle.OPEN);
                    } else {
                        g.drawLine((int) Math.round(p1.getX()), (int) Math.round(p1.getY()),
                                (int) Math.round(p2.getX()), (int) Math.round(p2.getY()));
                    }
                    n1 = n2;
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    @Override
    public boolean isLink() {
        return false;
    }

    /**
     * @return the transition
     */
    public Collection<MTransition> getTransitions() {
        return Collections.unmodifiableCollection(transitions);
    }

    @Override
    protected String getStoreType() {
        return "Transition";
    }

    /**
     * @return the fReflexivePosition
     */
    @Override
    public Direction getReflexivePosition() {
        return fReflexivePosition;
    }

    /**
     * @param fReflexivePosition
     *            the fReflexivePosition to set
     */
    @Override
    public void setReflexivePosition(Direction fReflexivePosition) {
        this.fReflexivePosition = fReflexivePosition;
    }

    @Override
    public PlaceableNode findNode(double x, double y) {
        for (TransitionLabel label : this.labels) {
            if (label.occupies(x, y))
                return label;
        }

        return super.findNode(x, y);
    }

    @Override
    protected void storeProperties(PersistHelper helper, boolean hidden, Element edgeElement) {
        // Properties are stored in additional info
    }

    @Override
    protected void storeAdditionalInfo(PersistHelper helper, Element element, boolean hidden) {
        super.storeAdditionalInfo(helper, element, hidden);

        if (isReflexive())
            helper.appendChild(element, "reflexivePosition", fReflexivePosition.toString());

        Document doc = element.getOwnerDocument();
        Element transitionsElement = doc.createElement("Transitions");
        element.appendChild(transitionsElement);

        for (int i = 0; i < this.transitions.size(); ++i) {
            MTransition transition = this.transitions.get(i);
            Element transitionElement = doc.createElement("Transition");
            transitionsElement.appendChild(transitionElement);

            helper.appendChild(transitionElement, "trigger",
                    (transition.getTrigger() == null ? "" : transition.getTrigger().toString()));
            helper.appendChild(transitionElement, "guard",
                    (transition.getGuard() == null ? "" : transition.getGuard().toString()));

            if (transition instanceof MProtocolTransition) {
                MProtocolTransition pt = (MProtocolTransition) transition;
                helper.appendChild(transitionElement, "post",
                        (pt.getPostCondition() == null ? "" : pt.getPostCondition().toString()));
            }

            this.labels.get(i).storePlacementInfo(helper, transitionElement, hidden);
        }
    }

    @Override
    protected void restoreAdditionalInfo(PersistHelper helper, int version) {
        if (isReflexive()) {
            String pos = helper.getElementStringValue("reflexivePosition");
            try {
                fReflexivePosition = Direction.valueOf(Direction.class, pos);
            } catch (NullPointerException e) {
            }
        }

        super.restoreAdditionalInfo(helper, version);
    }

    /**
     * @param t
     * @param helper
     */
    public void restoreLabel(MTransition t, PersistHelper helper, int version) {
        TransitionLabel l = this.labels.get(this.transitions.indexOf(t));
        l.restorePlacementInfo(helper, version);
    }

    /**
     * Removes all additional (merged) transitions from this edge. 
     * @return The set of removed transitions.
     */
    public Set<MTransition> flatten() {
        if (transitions.size() == 1)
            return Collections.emptySet();

        Set<MTransition> removed = new HashSet<MTransition>();
        while (transitions.size() > 1) {
            int lastIndex = transitions.size() - 1;
            MTransition t = transitions.get(lastIndex);
            transitions.remove(lastIndex);
            TransitionLabel removedLabel = labels.remove(lastIndex);
            removedLabel.dispose();
            removed.add(t);
            this.edgeProperties.remove(PropertyOwner.EDGE, removedLabel);
        }

        return removed;
    }

    /**
     * @param source
     * @param target
     * @param edgeName
     * @param diagram
     */
    public static TransitionEdge create(MTransition transition, VertexNode source, VertexNode target,
            String edgeName, DiagramOptions diagramOptions, Direction reflexivePosition) {
        TransitionEdge edge = new TransitionEdge(transition, source, target, edgeName, diagramOptions,
                reflexivePosition);
        edge.initialize();
        return edge;
    }
}