/* $Id: UMLDeploymentDiagram.java 17857 2010-01-12 19:59:07Z linus $
*****************************************************************************
* Copyright (c) 2009 Contributors - see below
* 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:
* bobtarling
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 2003-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.diagram.deployment.ui;
import java.awt.Point;
import java.awt.Rectangle;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.Action;
import org.apache.log4j.Logger;
import org.argouml.i18n.Translator;
import org.argouml.model.Facade;
import org.argouml.model.Model;
import org.argouml.ui.CmdCreateNode;
import org.argouml.uml.diagram.DiagramElement;
import org.argouml.uml.diagram.DiagramSettings;
import org.argouml.uml.diagram.deployment.DeploymentDiagramGraphModel;
import org.argouml.uml.diagram.static_structure.ui.FigClass;
import org.argouml.uml.diagram.static_structure.ui.FigComment;
import org.argouml.uml.diagram.static_structure.ui.FigInterface;
import org.argouml.uml.diagram.static_structure.ui.FigPackage;
import org.argouml.uml.diagram.ui.ActionSetAddAssociationMode;
import org.argouml.uml.diagram.ui.ActionSetMode;
import org.argouml.uml.diagram.ui.FigNodeAssociation;
import org.argouml.uml.diagram.ui.FigNodeModelElement;
import org.argouml.uml.diagram.ui.RadioAction;
import org.argouml.uml.diagram.ui.UMLDiagram;
import org.argouml.uml.diagram.use_case.ui.FigActor;
import org.argouml.uml.diagram.use_case.ui.FigUseCase;
import org.argouml.util.ToolBarUtility;
import org.tigris.gef.base.LayerPerspective;
import org.tigris.gef.base.LayerPerspectiveMutable;
import org.tigris.gef.base.ModeCreatePolyEdge;
import org.tigris.gef.presentation.FigNode;
/**
* The base class of the deployment diagram.<p>
*
* Defines the toolbar, provides for its initialization and provides
* constructors for a top level diagram and one within a defined
* namespace.<p>
*
* @author Clemens Eichler
*/
public class UMLDeploymentDiagram extends UMLDiagram {
/**
* Logger.
*/
private static final Logger LOG =
Logger.getLogger(UMLDeploymentDiagram.class);
////////////////
// actions for toolbar
private Action actionMNode;
private Action actionMNodeInstance;
private Action actionMComponent;
private Action actionMComponentInstance;
private Action actionMClass;
private Action actionMInterface;
private Action actionMObject;
private Action actionMDependency;
private Action actionMAssociation;
private Action actionMLink;
private Action actionAssociation;
private Action actionAggregation;
private Action actionComposition;
private Action actionUniAssociation;
private Action actionUniAggregation;
private Action actionUniComposition;
private Action actionMGeneralization;
private Action actionMAbstraction;
/**
* Constructor.
* @deprecated for 0.28 by tfmorris. Use
* {@link #UMLActivityDiagram(String, Object, GraphModel)}.
*/
@Deprecated
public UMLDeploymentDiagram() {
try {
setName(getNewDiagramName());
} catch (PropertyVetoException pve) { }
// TODO: All super constrcutors should take a GraphModel
setGraphModel(createGraphModel());
}
/**
* @param namespace the namespace for the new diagram
* @deprecated for 0.28 by tfmorris. Use
* {@link #UMLActivityDiagram(String, Object, GraphModel)}.
*/
@Deprecated
public UMLDeploymentDiagram(Object namespace) {
this();
setNamespace(namespace);
}
/**
* Method to perform a number of important initializations of a
* <em>Deployment Diagram</em>.<p>
*
* Each diagram type has a similar <em>UMLxxxDiagram</em> class.<p>
*
* Changed <em>lay</em> from <em>LayerPerspective</em> to
* <em>LayerPerspectiveMutable</em>. This class is a child of
* <em>LayerPerspective</em> and was implemented to correct some
* difficulties in changing the model. <em>lay</em> is used mainly
* in <em>LayerManager</em>(GEF) to control the adding, changing and
* deleting layers on the diagram...<p>
*
* @param handle package from the model
* @author psager@tigris.org Jan. 24, 2002
*/
public void setNamespace(Object handle) {
if (!Model.getFacade().isANamespace(handle)) {
LOG.error(
"Illegal argument. Object " + handle + " is not a namespace");
throw new IllegalArgumentException(
"Illegal argument. Object " + handle + " is not a namespace");
}
Object m = handle;
boolean init = (null == getNamespace());
super.setNamespace(m);
DeploymentDiagramGraphModel gm = createGraphModel();
gm.setHomeModel(m);
if (init) {
LayerPerspective lay =
new LayerPerspectiveMutable(Model.getFacade().getName(m), gm);
DeploymentDiagramRenderer rend = new DeploymentDiagramRenderer();
lay.setGraphNodeRenderer(rend);
lay.setGraphEdgeRenderer(rend);
setLayer(lay);
}
}
// TODO: Needs to be tidied up after stable release. Graph model
// should be created in constructor
private DeploymentDiagramGraphModel createGraphModel() {
if ((getGraphModel() instanceof DeploymentDiagramGraphModel)) {
return (DeploymentDiagramGraphModel) getGraphModel();
} else {
return new DeploymentDiagramGraphModel();
}
}
/*
* @see org.argouml.uml.diagram.ui.UMLDiagram#getUmlActions()
*/
protected Object[] getUmlActions() {
Object[] actions = {
getActionMNode(),
getActionMNodeInstance(),
getActionMComponent(),
getActionMComponentInstance(),
getActionMGeneralization(),
getActionMAbstraction(),
getActionMDependency(),
getAssociationActions(),
getActionMObject(),
getActionMLink(),
};
return actions;
}
private Object[] getAssociationActions() {
Object[][] actions = {
{getActionAssociation(), getActionUniAssociation() },
{getActionAggregation(), getActionUniAggregation() },
{getActionComposition(), getActionUniComposition() },
};
ToolBarUtility.manageDefault(actions, "diagram.deployment.association");
return actions;
}
/**
* The UID.
*/
static final long serialVersionUID = -375918274062198744L;
/*
* @see org.argouml.uml.diagram.ui.UMLDiagram#getLabelName()
*/
public String getLabelName() {
return Translator.localize("label.deployment-diagram");
}
//////////////////////////////
// Getters for plugin modules:
//////////////////////////////
/**
* @return Returns the actionAggregation.
*/
protected Action getActionAggregation() {
if (actionAggregation == null) {
actionAggregation =
new RadioAction(
new ActionSetAddAssociationMode(
Model.getAggregationKind().getAggregate(),
false,
"button.new-aggregation"));
}
return actionAggregation;
}
/**
* @return Returns the actionAssociation.
*/
protected Action getActionAssociation() {
if (actionAssociation == null) {
actionAssociation =
new RadioAction(
new ActionSetAddAssociationMode(
Model.getAggregationKind().getNone(),
false,
"button.new-association"));
}
return actionAssociation;
}
/**
* @return Returns the actionComposition.
*/
protected Action getActionComposition() {
if (actionComposition == null) {
actionComposition =
new RadioAction(
new ActionSetAddAssociationMode(
Model.getAggregationKind().getComposite(),
false,
"button.new-composition"));
}
return actionComposition;
}
/**
* @return Returns the actionMAssociation.
*/
protected Action getActionMAssociation() {
if (actionMAssociation == null) {
actionMAssociation =
new RadioAction(new ActionSetMode(
ModeCreatePolyEdge.class,
"edgeClass",
Model.getMetaTypes().getAssociation(),
"button.new-association"));
}
return actionMAssociation;
}
/**
* @return Returns the actionMClass.
*/
protected Action getActionMClass() {
if (actionMClass == null) {
actionMClass =
new RadioAction(
new CmdCreateNode(Model.getMetaTypes().getUMLClass(),
"button.new-class"));
}
return actionMClass;
}
/**
* @return Returns the actionMComponent.
*/
protected Action getActionMComponent() {
if (actionMComponent == null) {
actionMComponent =
new RadioAction(
new CmdCreateNode(
Model.getMetaTypes().getComponent(),
"button.new-component"));
}
return actionMComponent;
}
/**
* @return Returns the actionMComponentInstance.
*/
protected Action getActionMComponentInstance() {
if (actionMComponentInstance == null) {
actionMComponentInstance =
new RadioAction(new CmdCreateNode(
Model.getMetaTypes().getComponentInstance(),
"button.new-componentinstance"));
}
return actionMComponentInstance;
}
/**
* @return Returns the actionMDependency.
*/
protected Action getActionMDependency() {
if (actionMDependency == null) {
actionMDependency =
new RadioAction(new ActionSetMode(
ModeCreatePolyEdge.class,
"edgeClass",
Model.getMetaTypes().getDependency(),
"button.new-dependency"));
}
return actionMDependency;
}
/**
* @return Returns the actionMGeneralization.
*/
protected Action getActionMGeneralization() {
if (actionMGeneralization == null) {
actionMGeneralization =
new RadioAction(new ActionSetMode(
ModeCreatePolyEdge.class,
"edgeClass",
Model.getMetaTypes().getGeneralization(),
"button.new-generalization"));
}
return actionMGeneralization;
}
/**
* @return Returns the actionMAbstraction.
*/
protected Action getActionMAbstraction() {
if (actionMAbstraction == null) {
actionMAbstraction =
new RadioAction(new ActionSetMode(
ModeCreatePolyEdge.class,
"edgeClass",
Model.getMetaTypes().getAbstraction(),
"button.new-realization"));
}
return actionMAbstraction;
}
/**
* @return Returns the actionMInterface.
*/
protected Action getActionMInterface() {
if (actionMInterface == null) {
actionMInterface =
new RadioAction(
new CmdCreateNode(
Model.getMetaTypes().getInterface(),
"button.new-interface"));
}
return actionMInterface;
}
/**
* @return Returns the actionMLink.
*/
protected Action getActionMLink() {
if (actionMLink == null) {
actionMLink =
new RadioAction(new ActionSetMode(
ModeCreatePolyEdge.class,
"edgeClass",
Model.getMetaTypes().getLink(),
"button.new-link"));
}
return actionMLink;
}
/**
* @return Returns the actionMNode.
*/
protected Action getActionMNode() {
if (actionMNode == null) {
actionMNode =
new RadioAction(new CmdCreateNode(
Model.getMetaTypes().getNode(),
"button.new-node"));
}
return actionMNode;
}
/**
* @return Returns the actionMNodeInstance.
*/
protected Action getActionMNodeInstance() {
if (actionMNodeInstance == null) {
actionMNodeInstance =
new RadioAction(new CmdCreateNode(
Model.getMetaTypes().getNodeInstance(),
"button.new-nodeinstance"));
}
return actionMNodeInstance;
}
/**
* @return Returns the actionMObject.
*/
protected Action getActionMObject() {
if (actionMObject == null) {
actionMObject =
new RadioAction(
new CmdCreateNode(Model.getMetaTypes().getObject(),
"button.new-object"));
}
return actionMObject;
}
/**
* @return Returns the actionUniAggregation.
*/
protected Action getActionUniAggregation() {
if (actionUniAggregation == null) {
actionUniAggregation =
new RadioAction(
new ActionSetAddAssociationMode(
Model.getAggregationKind().getAggregate(),
true, "button.new-uniaggregation"));
}
return actionUniAggregation;
}
/**
* @return Returns the actionUniAssociation.
*/
protected Action getActionUniAssociation() {
if (actionUniAssociation == null) {
actionUniAssociation =
new RadioAction(
new ActionSetAddAssociationMode(
Model.getAggregationKind().getNone(),
true, "button.new-uniassociation"));
}
return actionUniAssociation;
}
/**
* @return Returns the actionUniComposition.
*/
protected Action getActionUniComposition() {
if (actionUniComposition == null) {
actionUniComposition =
new RadioAction(
new ActionSetAddAssociationMode(
Model.getAggregationKind().getComposite(),
true, "button.new-unicomposition"));
}
return actionUniComposition;
}
/*
* @see org.argouml.uml.diagram.ui.UMLDiagram#isRelocationAllowed(java.lang.Object)
*/
public boolean isRelocationAllowed(Object base) {
return Model.getFacade().isAPackage(base);
}
@SuppressWarnings("unchecked")
public Collection getRelocationCandidates(Object root) {
return
Model.getModelManagementHelper().getAllModelElementsOfKindWithModel(
root, Model.getMetaTypes().getPackage());
}
/*
* @see org.argouml.uml.diagram.ui.UMLDiagram#relocate(java.lang.Object)
*/
public boolean relocate(Object base) {
setNamespace(base);
damage();
return true;
}
/**
* Provides the standard functionality of the superclass only for
* deployment diagram specific model elements
* @param modelElement the model element
* @param namespace the namespace (or null for diagram)
* @see org.argouml.uml.diagram.ui.UMLDiagram#setModelElementNamespace(java.lang.Object, Object)
*/
public void setModelElementNamespace(
Object modelElement,
Object namespace) {
Facade facade = Model.getFacade();
if (facade.isANode(modelElement)
|| facade.isANodeInstance(modelElement)
|| facade.isAComponent(modelElement)
|| facade.isAComponentInstance(modelElement)) {
LOG.info("Setting namespace of " + modelElement);
super.setModelElementNamespace(modelElement, namespace);
}
}
/*
* If the new encloser is null, and the old one is a Component,
* then the "enclosed" Fig has been moved on the diagram.
* This causes the model to be adapted as follows:
* remove the elementResidence
* between the "enclosed" and the oldEncloser.
*
* @see org.argouml.ui.ArgoDiagram#changeFigEncloser(org.tigris.gef.presentation.FigNode, org.tigris.gef.presentation.FigNode, org.tigris.gef.presentation.FigNode)
*/
public void encloserChanged(FigNode enclosed, FigNode oldEncloser,
FigNode newEncloser) {
if (oldEncloser != null && newEncloser == null
&& Model.getFacade().isAComponent(oldEncloser.getOwner())) {
Collection<Object> er1 = Model.getFacade().getElementResidences(
enclosed.getOwner());
Collection er2 = Model.getFacade().getResidentElements(
oldEncloser.getOwner());
Collection<Object> common = new ArrayList<Object>(er1);
common.retainAll(er2);
for (Object elementResidence : common) {
Model.getUmlFactory().delete(elementResidence);
}
}
}
@Override
public boolean doesAccept(Object objectToAccept) {
if (Model.getFacade().isANode(objectToAccept)) {
return true;
} else if (Model.getFacade().isAAssociation(objectToAccept)) {
return true;
} else if (Model.getFacade().isANodeInstance(objectToAccept)) {
return true;
} else if (Model.getFacade().isAComponent(objectToAccept)) {
return true;
} else if (Model.getFacade().isAComponentInstance(objectToAccept)) {
return true;
} else if (Model.getFacade().isAClass(objectToAccept)) {
return true;
} else if (Model.getFacade().isAInterface(objectToAccept)) {
return true;
} else if (Model.getFacade().isAObject(objectToAccept)) {
return true;
} else if (Model.getFacade().isAComment(objectToAccept)) {
return true;
} else if (Model.getFacade().isAActor(objectToAccept)) {
return true;
}
return false;
}
public DiagramElement createDiagramElement(
final Object modelElement,
final Rectangle bounds) {
FigNodeModelElement figNode = null;
DiagramSettings settings = getDiagramSettings();
if (Model.getFacade().isANode(modelElement)) {
figNode = new FigMNode(modelElement, bounds, settings);
} else if (Model.getFacade().isAAssociation(modelElement)) {
figNode =
createNaryAssociationNode(modelElement, bounds, settings);
} else if (Model.getFacade().isANodeInstance(modelElement)) {
figNode = new FigNodeInstance(modelElement, bounds, settings);
} else if (Model.getFacade().isAComponent(modelElement)) {
figNode = new FigComponent(modelElement, bounds, settings);
} else if (Model.getFacade().isAComponentInstance(modelElement)) {
figNode = new FigComponentInstance(modelElement, bounds, settings);
} else if (Model.getFacade().isAClass(modelElement)) {
figNode = new FigClass(modelElement, bounds, settings);
} else if (Model.getFacade().isAInterface(modelElement)) {
figNode = new FigInterface(modelElement, bounds, settings);
} else if (Model.getFacade().isAObject(modelElement)) {
figNode = new FigObject(modelElement, bounds, settings);
} else if (Model.getFacade().isAActor(modelElement)) {
figNode = new FigActor(modelElement, bounds, settings);
} else if (Model.getFacade().isAComment(modelElement)) {
figNode = new FigComment(modelElement, bounds, settings);
}
if (figNode != null) {
LOG.debug("Model element " + modelElement + " converted to "
+ figNode);
} else {
LOG.debug("Dropped object NOT added " + figNode);
}
return figNode;
}
}