Ptidej-v5.2-master/POM Tests/data/ArgoUML_0.28/src/org/argouml/uml/diagram/ui/ModeCreateAssociationEnd.java
// $Id: ModeCreateAssociationEnd.java 16689 2009-01-23 22:05:04Z bobtarling $
// Copyright (c) 2005-2007 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies.  This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason.  IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

package org.argouml.uml.diagram.ui;

import java.awt.Color;
import java.util.Collection;
import java.util.List;

import org.argouml.model.IllegalModelElementConnectionException;
import org.argouml.model.Model;
import org.argouml.uml.diagram.static_structure.ui.FigClass;
import org.argouml.uml.diagram.static_structure.ui.FigClassifierBox;
import org.tigris.gef.base.Layer;
import org.tigris.gef.base.LayerPerspective;
import org.tigris.gef.graph.MutableGraphModel;
import org.tigris.gef.presentation.Fig;
import org.tigris.gef.presentation.FigEdge;
import org.tigris.gef.presentation.FigNode;

/**
 * A Mode to interpret user input while creating an association end.
 * The association end can connect an existing association to an existing
 * classifier.
 * If the association is an n-ary association (diamond shape node) then
 * the edge is simply added.
 * If the association is a binary association edge then that edge is
 * transformed into a n-ary association.
 * TODO: Investigate if this can extend ModeCreateGraphEdge
 *
 * @author Bob Tarling
 */
public class ModeCreateAssociationEnd extends ModeCreateGraphEdge {

    /**
     * The UID.
     */
    private static final long serialVersionUID = -7249069222789301797L;
    
    public Object getMetaType() {
        return Model.getMetaTypes().getAssociationEnd();
    }
    
    /**
     * Create an edge of the given type and connect it to the
     * given nodes.
     *
     * @param graphModel     the graph model in which to create the connection
     *                       element
     * @param edgeType       the UML object type of the connection
     * @param sourceFig      the FigNode for the source element
     * @param destFig        the FigNode for the destination element
     * @return The FigEdge representing the newly created model element
     */
    @Override
    protected FigEdge buildConnection(
            MutableGraphModel graphModel,
            Object edgeType,
            Fig sourceFig,
            Fig destFig) {
        try {
            // The source of an association end should not
            // be the classifier. If it is the user has drawn the wrong way
            // round so we swap here.
            if (sourceFig instanceof FigClassifierBox) {
                final Fig tempFig = sourceFig;
                sourceFig = destFig;
                destFig = tempFig;
            }
            
            Object associationEnd = 
                Model.getUmlFactory().buildConnection(
                    edgeType,
                    sourceFig.getOwner(),
                    null,
                    destFig.getOwner(),
                    null,
                    null,
                    null);
            
            final FigNode sourceFigNode = convertToFigNode(sourceFig);
            final FigNode destFigNode = convertToFigNode(destFig);
            
            graphModel.addEdge(associationEnd);
            
            setNewEdge(associationEnd);

            // Calling connect() will add the edge to the GraphModel and
            // any LayerPersectives on that GraphModel will get a
            // edgeAdded event and will add an appropriate FigEdge
            // (determined by the GraphEdgeRenderer).

            if (getNewEdge() != null) {
                sourceFigNode.damage();
                destFigNode.damage();
                Layer lay = editor.getLayerManager().getActiveLayer();
                FigEdge fe = (FigEdge) lay.presentationFor(getNewEdge());
                _newItem.setLineColor(Color.black);
                fe.setFig(_newItem);
                fe.setSourcePortFig(sourceFigNode);
                fe.setSourceFigNode(sourceFigNode);
                fe.setDestPortFig(destFigNode);
                fe.setDestFigNode(destFigNode);
                return fe;
            } else {
                return null;
            }
        } catch (IllegalModelElementConnectionException e) {
            // We have already confirmed the connection is valid
            return null;
        }
    }
    
    /**
     * If the selected Fig is a FigAssociation (an edge) then
     * convert it to a FigNodeAssociation.
     * @param fig the select end Fig
     * @return the fig converted to a FigNode
     */
    private FigNode convertToFigNode(Fig fig) {
        if (fig instanceof FigEdgePort) {
            fig = fig.getGroup();
        }
        if (!(fig instanceof FigAssociation)) {
            return (FigNode) fig;
        }
        final FigAssociation figAssociation = (FigAssociation) fig;
        final int x = figAssociation.getEdgePort().getX();
        final int y = figAssociation.getEdgePort().getY();
        final Object association = fig.getOwner();
        final FigNode originalEdgePort = figAssociation.getEdgePort();
        
        FigClassAssociationClass associationClassBox = null;
        FigEdgeAssociationClass associationClassLink = null;
        
        final LayerPerspective lay = 
            (LayerPerspective) editor.getLayerManager().getActiveLayer();
        
        // Detach any edges (such as comment edges) already attached
        // to the FigAssociation before the FigAssociation is removed.
        // They'll later be re-attached to the new FigNodeAssociation
        final Collection<FigEdge> existingEdges = originalEdgePort.getEdges();
        for (FigEdge edge : existingEdges) {
            if (edge instanceof FigEdgeAssociationClass) {
                // If there are bits of an association class then
                // remember their location and path.
                associationClassLink = (FigEdgeAssociationClass) edge;
                FigNode figNode = edge.getSourceFigNode();
                if (figNode instanceof FigEdgePort) {
                    figNode = edge.getDestFigNode();
                }
                associationClassBox = (FigClassAssociationClass) figNode;
                originalEdgePort.removeFigEdge(edge);
                lay.remove(edge);
                lay.remove(associationClassBox);
            } else {
                originalEdgePort.removeFigEdge(edge);
            }
        }
        
        List associationFigs = lay.presentationsFor(association);
        
        figAssociation.removeFromDiagram();
        associationFigs = lay.presentationsFor(association);
        
        // Create the new FigNodeAssociation and locate it.
        final MutableGraphModel gm =
            (MutableGraphModel) editor.getGraphModel();
        gm.addNode(association);
        associationFigs = lay.presentationsFor(association);
        associationFigs.remove(figAssociation);
        associationFigs = lay.presentationsFor(association);
        
        final FigNodeAssociation figNode = 
            (FigNodeAssociation) associationFigs.get(0);
        
        figNode.setLocation(
                x - figNode.getWidth() / 2,
                y - figNode.getHeight() / 2);
        editor.add(figNode);
        editor.getSelectionManager().deselectAll();
        
        // Add the association ends to the graph model
        final Collection<Object> associationEnds =
            Model.getFacade().getConnections(association);
        
        for (Object associationEnd : associationEnds) {
            gm.addEdge(associationEnd);
        }
        
        // Add the edges (such as comment edges) that were on the old
        // FigAssociation to our new FigNodeAssociation and make sure they are
        // positioned correctly.
        for (FigEdge edge : existingEdges) {
            if (edge.getDestFigNode() == originalEdgePort) {
                edge.setDestFigNode(figNode);
                edge.setDestPortFig(figNode);
            }
            if (edge.getSourceFigNode() == originalEdgePort) {
                edge.setSourceFigNode(figNode);
                edge.setSourcePortFig(figNode);
            }
        }
        figNode.updateEdges();
        
        if (associationClassBox != null) {
            associationFigs = lay.presentationsFor(association);
            
            lay.add(associationClassBox);
            associationClassLink.setSourceFigNode(figNode);
            lay.add(associationClassLink);
            
            associationFigs = lay.presentationsFor(association);
        }

        return figNode;
    }
    
} /* end class ModeCreateAssociation */
