Ptidej-v5.2-master/POM Tests/data/ArgoUML_0.28/src/org/argouml/uml/reveng/DiagramInterface.java
// $Id: DiagramInterface.java 16709 2009-01-26 20:27:23Z tfmorris $
// Copyright (c) 1996-2008 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.reveng;

import java.awt.Rectangle;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.argouml.kernel.Project;
import org.argouml.model.Model;
import org.argouml.uml.diagram.ArgoDiagram;
import org.argouml.uml.diagram.DiagramFactory;
import org.argouml.uml.diagram.static_structure.ClassDiagramGraphModel;
import org.argouml.uml.diagram.static_structure.ui.FigClass;
import org.argouml.uml.diagram.static_structure.ui.FigClassifierBox;
import org.argouml.uml.diagram.static_structure.ui.FigInterface;
import org.argouml.uml.diagram.static_structure.ui.FigPackage;
import org.tigris.gef.base.Editor;
import org.tigris.gef.base.LayerPerspective;
import org.tigris.gef.presentation.Fig;

/**
 * Instances of this class interface the current Class diagram.<p>
 *
 * This class is used by the import mechanism to create packages,
 * interfaces and classes within the diagrams.
 * It is also used to find the correct diagram to work in.
 *
 * @author Andreas Rueckert
 * @since 0.9
 */
public class DiagramInterface {

    private static final char DIAGRAM_NAME_SEPARATOR = '_';
    private static final String DIAGRAM_NAME_SUFFIX = "classes";

    private static final Logger LOG =
        Logger.getLogger(DiagramInterface.class);

    private Editor currentEditor;

    /**
     * To know what diagrams we have to layout after the import,
     * we store them in this list.
     */
    private List<ArgoDiagram> modifiedDiagrams = 
        new ArrayList<ArgoDiagram>();

    /**
     * The current GraphModel of the current classdiagram.
     */
    private ClassDiagramGraphModel currentGM;

    /**
     * The current Layer of the current classdiagram.
     */
    private LayerPerspective currentLayer;

    /**
     * The current diagram for the isInDiagram method.
     */
    private ArgoDiagram currentDiagram;

    private Project currentProject;
    
    /**
     * Creates a new DiagramInterface.
     *
     * @param editor The editor to operate on.
     */
    public DiagramInterface(Editor editor) {
  	currentEditor = editor;
  	LayerPerspective layer = 
  	    (LayerPerspective) editor.getLayerManager().getActiveLayer();
  	currentProject = ((ArgoDiagram) layer.getDiagram()).getProject();
    }

    /**
     * Creates a new DiagramInterface.
     *
     * @param editor The editor to operate on.
     * @param project the project being operated on
     */
    public DiagramInterface(Editor editor, Project project) {
        currentEditor = editor;
    }
    
    /**
     * Get the current editor.
     *
     * @return The current editor.
     */
    Editor getEditor() {
	return currentEditor;
    }

    /**
     * Mark a diagram as modified, so we can layout it, after the
     * import is complete.<p>
     *
     * If the diagram is not already marked, add it to the list.<p>
     *
     * @param diagram The diagram to mark as modified.
     */
    void markDiagramAsModified(ArgoDiagram diagram) {
        if (!modifiedDiagrams.contains(diagram)) {
            modifiedDiagrams.add(diagram);
        }
    }
    

    /**
     * Get the list of modified diagrams.
     *
     * @return The list of modified diagrams.
     */
    public List<ArgoDiagram> getModifiedDiagramList() {
        return modifiedDiagrams;
    }
    
    /**
     * Reset the list of modified diagrams.
     */
    void resetModifiedDiagrams() {
	modifiedDiagrams = new ArrayList<ArgoDiagram>();
    }

    /**
     * Add a package to the current diagram. If the package already has
     * a representation in the current diagram, it is not(!) added.
     *
     * @param newPackage The package to add.
     */
    public void addPackage(Object newPackage) {
        if (!isInDiagram(newPackage)) {
            if (currentGM.canAddNode(newPackage)) {
                FigPackage newPackageFig = new FigPackage(newPackage,
                        new Rectangle(0, 0, 0, 0), currentDiagram
                                .getDiagramSettings());
                currentLayer.add(newPackageFig);
                currentGM.addNode(newPackage);
                currentLayer.putInPosition(newPackageFig);
            }
        }
    }

    /**
     * Check if a given package has a representation in the current
     * diagram.
     *
     * @param p The package to lookup in the current diagram.
     * @return true if this package has a figure in the current diagram,
     *         false otherwise.
     */
    public boolean isInDiagram(Object p) {
	if (currentDiagram == null) {
            return false;
        } else {
            return currentDiagram.getNodes().contains(p);
        }
    }

    /**
     * Check if this diagram already exists in the project.<p>
     *
     * @param name package name (converted to class name)
     * @return true if diagram exists in project.
     */
    public boolean isDiagramInProject(String name) {
        if (currentProject == null) {
            throw new RuntimeException("current project not set yet");
        }
        return currentProject.getDiagram(getDiagramName(name)) != null;
    }

    /**
     * Create a diagram name from a package name.
     *
     * @param packageName The package name.
     * @return The name for the diagram.
     */
    private String getDiagramName(String packageName) {
        /*
         * TODO: This transformation is Java specific. We need a more
         * language/notation scheme for specifying qualified names.
         * Possible algorithm - replace all punctuation with our
         * internal separator, replace multiple separators with a single
         * instance (for languages like C++).  What about I18N? - tfm
         */
	return packageName.replace('.', DIAGRAM_NAME_SEPARATOR)
                + DIAGRAM_NAME_SEPARATOR + DIAGRAM_NAME_SUFFIX;
    }

    /**
     * Select a class diagram as the current diagram, creating it
     * if necessary.
     *
     * @param p The package.
     * @param name The fully qualified name of this package.
     */
    public void selectClassDiagram(Object p, String name) {
        // Check if this diagram already exists in the project
        if (currentProject == null) {
            throw new RuntimeException("current project not set yet");
        }
        ArgoDiagram m = currentProject.getDiagram(getDiagramName(name));
        if (m != null) {
            // The diagram already exists in this project. Select it
            // as the current target.
            setCurrentDiagram(m);
        } else {
            // Otherwise create a new classdiagram for the package.
            addClassDiagram(p, name);
        }
    }

    /**
     * Add a new class diagram for a package to the project.
     * 
     * @param ns
     *            The namespace to contain the diagram. If null, the root model
     *            will be used.
     * @param name
     *            The fully qualified name of the package, which is used to
     *            generate the diagram name from.
     */
    public void addClassDiagram(Object ns, String name) {
        if (currentProject == null) {
            throw new RuntimeException("current project not set yet");
        }
        ArgoDiagram d = DiagramFactory.getInstance().createDiagram(
                DiagramFactory.DiagramType.Class,
                ns == null ? currentProject.getRoot() : ns, null);

        try {
            d.setName(getDiagramName(name));
        } catch (PropertyVetoException pve) { 
            LOG.error("Failed to set diagram name.", pve);
        }
        currentProject.addMember(d);
        setCurrentDiagram(d);
    }

    /**
     * Add a class to the current diagram.
     *
     * @param newClass The new class to add to the editor.
     * @param minimise minimise the class fig by hiding compartiments
     *                 (of attributes and operations)
     */
    public void addClass(Object newClass, boolean minimise) {
        addClassifier(newClass, minimise);
    }

    /**
     * Add a classier to the current diagram.
     *
     * @param classifier The new class or interface to add to the editor.
     * @param minimise minimise the class fig by hiding compartments
     *                 (of attributes and operations)
     */
    private void addClassifier(Object classifier, boolean minimise) {
        // if the classifier is not in the current diagram, add it:
        if (currentGM.canAddNode(classifier)) {
            FigClassifierBox newFig;
            if (Model.getFacade().isAClass(classifier)) {
                newFig = new FigClass(classifier, new Rectangle(0, 0, 0, 0),
                        currentDiagram.getDiagramSettings());
            } else if (Model.getFacade().isAInterface(classifier)) {
                newFig = new FigInterface(classifier,
                        new Rectangle(0, 0, 0, 0), currentDiagram
                                .getDiagramSettings());
            } else {
                return;
            }
            
            /*
             * The following calls are ORDER DEPENDENT. Not sure why, but the
             * layer add must come before the model add or we'll end up with
             * duplicate figures in the diagram. - tfm
             */            
            currentLayer.add(newFig);
            currentGM.addNode(classifier);
            currentLayer.putInPosition(newFig);

            newFig.setOperationsVisible(!minimise);
            if (Model.getFacade().isAClass(classifier)) {            
                ((FigClass) newFig).setAttributesVisible(!minimise);
            }

            newFig.renderingChanged();
        } else {
            // the class is in the diagram
            // so we are on a second pass,
            // find the fig for this class can update its visible state.
            FigClassifierBox existingFig = null;
            List figs = currentLayer.getContentsNoEdges();
            for (int i = 0; i < figs.size(); i++) {
                Fig fig = (Fig) figs.get(i);
                if (classifier == fig.getOwner()) {
                    existingFig = (FigClassifierBox) fig;
                }
            }
            existingFig.renderingChanged();
        }

        // add edges
        // for a 2-pass r.e. process we might have already added the
        // class but not its edges
	currentGM.addNodeRelatedEdges(classifier);
    }

    /**
     * Add a interface to the current diagram.
     *
     * @param newInterface The interface to add.
     * @param minimise minimise the class fig by hiding compartiments
     *                 (of attributes and operations)
     */
    public void addInterface(Object newInterface, boolean minimise) {
        addClassifier(newInterface, minimise);
    }


    /**
     * Creates class diagram under the root.
     * Is used for classes out of packages.
     *
     */
    public void createRootClassDiagram() {
	selectClassDiagram(null, "");
    }

    /**
     * selects a diagram without affecting the gui.
     *
     * @param diagram the diagram
     */
    public void setCurrentDiagram(ArgoDiagram diagram) {
        if (diagram == null) {
            throw new RuntimeException("you can't select a null diagram");
        }

        currentGM = (ClassDiagramGraphModel) diagram.getGraphModel();
        currentLayer = diagram.getLayer();
        currentDiagram = diagram;
        currentProject = diagram.getProject();
        
        markDiagramAsModified(diagram);
    }

}

























