Coverage Report - org.argouml.ui.explorer.ExplorerPopup
 
Classes in this File Line Coverage Branch Coverage Complexity
ExplorerPopup
0%
0/195
0%
0/186
5.905
ExplorerPopup$ActionAddExistingRelatedNode
0%
0/23
0%
0/6
5.905
ExplorerPopup$ActionCreateAssociation
0%
0/12
0%
0/2
5.905
ExplorerPopup$ActionCreateAssociationRole
0%
0/12
0%
0/2
5.905
ExplorerPopup$OrderedMenu
0%
0/5
N/A
5.905
ExplorerPopup$OrderedMenuItem
0%
0/9
N/A
5.905
 
 1  
 /* $Id: ExplorerPopup.java 18629 2010-08-05 11:57:42Z bobtarling $
 2  
  *****************************************************************************
 3  
  * Copyright (c) 2009-2010 Contributors - see below
 4  
  * All rights reserved. This program and the accompanying materials
 5  
  * are made available under the terms of the Eclipse Public License v1.0
 6  
  * which accompanies this distribution, and is available at
 7  
  * http://www.eclipse.org/legal/epl-v10.html
 8  
  *
 9  
  * Contributors:
 10  
  *    Bob Tarling
 11  
  *    Michiel van der Wulp
 12  
  *****************************************************************************
 13  
  *
 14  
  * Some portions of this file was previously release using the BSD License:
 15  
  */
 16  
 
 17  
 // Copyright (c) 1996-2009 The Regents of the University of California. All
 18  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 19  
 // software and its documentation without fee, and without a written
 20  
 // agreement is hereby granted, provided that the above copyright notice
 21  
 // and this paragraph appear in all copies.  This software program and
 22  
 // documentation are copyrighted by The Regents of the University of
 23  
 // California. The software program and documentation are supplied "AS
 24  
 // IS", without any accompanying services from The Regents. The Regents
 25  
 // does not warrant that the operation of the program will be
 26  
 // uninterrupted or error-free. The end-user understands that the program
 27  
 // was developed for research purposes and is advised not to rely
 28  
 // exclusively on the program for any reason.  IN NO EVENT SHALL THE
 29  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 30  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 31  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 32  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 33  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 34  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 35  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 36  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 37  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 38  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 39  
 
 40  
 package org.argouml.ui.explorer;
 41  
 
 42  
 import java.awt.event.ActionEvent;
 43  
 import java.awt.event.MouseEvent;
 44  
 import java.util.ArrayList;
 45  
 import java.util.Collection;
 46  
 import java.util.Iterator;
 47  
 import java.util.List;
 48  
 import java.util.Set;
 49  
 import java.util.TreeSet;
 50  
 
 51  
 import javax.swing.AbstractAction;
 52  
 import javax.swing.Action;
 53  
 import javax.swing.JMenu;
 54  
 import javax.swing.JMenuItem;
 55  
 import javax.swing.JPopupMenu;
 56  
 import javax.swing.MenuElement;
 57  
 
 58  
 import org.apache.log4j.Logger;
 59  
 import org.argouml.i18n.Translator;
 60  
 import org.argouml.kernel.ActionList;
 61  
 import org.argouml.kernel.ProfileConfiguration;
 62  
 import org.argouml.kernel.Project;
 63  
 import org.argouml.kernel.ProjectManager;
 64  
 import org.argouml.model.IllegalModelElementConnectionException;
 65  
 import org.argouml.model.Model;
 66  
 import org.argouml.profile.Profile;
 67  
 import org.argouml.ui.ActionCreateContainedModelElement;
 68  
 import org.argouml.ui.ActionCreateEdgeModelElement;
 69  
 import org.argouml.ui.ContextActionFactoryManager;
 70  
 import org.argouml.ui.UndoableAction;
 71  
 import org.argouml.ui.targetmanager.TargetManager;
 72  
 import org.argouml.uml.diagram.ArgoDiagram;
 73  
 import org.argouml.uml.diagram.DiagramUtils;
 74  
 import org.argouml.uml.diagram.SequenceDiagram;
 75  
 import org.argouml.uml.diagram.activity.ui.UMLActivityDiagram;
 76  
 import org.argouml.uml.diagram.state.ui.UMLStateDiagram;
 77  
 import org.argouml.uml.diagram.static_structure.ui.UMLClassDiagram;
 78  
 import org.argouml.uml.diagram.ui.ActionAddAllClassesFromModel;
 79  
 import org.argouml.uml.diagram.ui.ActionAddExistingEdge;
 80  
 import org.argouml.uml.diagram.ui.ActionAddExistingNode;
 81  
 import org.argouml.uml.diagram.ui.ActionAddExistingNodes;
 82  
 import org.argouml.uml.diagram.ui.ActionSaveDiagramToClipboard;
 83  
 import org.argouml.uml.diagram.ui.ModeAddToDiagram;
 84  
 import org.argouml.uml.ui.ActionActivityDiagram;
 85  
 import org.argouml.uml.ui.ActionClassDiagram;
 86  
 import org.argouml.uml.ui.ActionCollaborationDiagram;
 87  
 import org.argouml.uml.ui.ActionDeleteModelElements;
 88  
 import org.argouml.uml.ui.ActionDeploymentDiagram;
 89  
 import org.argouml.uml.ui.ActionSequenceDiagram;
 90  
 import org.argouml.uml.ui.ActionSetSourcePath;
 91  
 import org.argouml.uml.ui.ActionStateDiagram;
 92  
 import org.argouml.uml.ui.ActionUseCaseDiagram;
 93  
 import org.tigris.gef.base.Diagram;
 94  
 import org.tigris.gef.base.Editor;
 95  
 import org.tigris.gef.base.Globals;
 96  
 import org.tigris.gef.graph.GraphModel;
 97  
 import org.tigris.gef.graph.MutableGraphModel;
 98  
 
 99  
 /**
 100  
  * PopUp for extra functionality for the Explorer.
 101  
  *
 102  
  * @author alexb
 103  
  * @since 0.15.2
 104  
  */
 105  0
 public class ExplorerPopup extends JPopupMenu {
 106  
 
 107  0
     private JMenu createDiagrams = 
 108  
         new JMenu(menuLocalize("menu.popup.create-diagram"));
 109  
     
 110  0
     private static final Logger LOG =
 111  
         Logger.getLogger(ExplorerPopup.class);
 112  
     
 113  
     /**
 114  
      * Array of model elements and corresponding il8n tag 
 115  
      * that are presented on the Create Model Elements menu.
 116  
      */
 117  0
     private static final Object[] MODEL_ELEMENT_MENUITEMS = 
 118  
         new Object[] {
 119  
             Model.getMetaTypes().getProfile(), // needs to be the first entry
 120  
             "button.new-profile-package", // because of UML1/UML2 differences
 121  
             Model.getMetaTypes().getParameter(),
 122  
             "button.new-parameter",
 123  
             Model.getMetaTypes().getTemplateParameter(),
 124  
             "button.new-template-parameter",
 125  
             Model.getMetaTypes().getPackage(), 
 126  
             "button.new-package",
 127  
             Model.getMetaTypes().getActor(), 
 128  
             "button.new-actor",
 129  
             Model.getMetaTypes().getUseCase(), 
 130  
             "button.new-usecase",
 131  
             Model.getMetaTypes().getExtensionPoint(), 
 132  
             "button.new-extension-point",
 133  
             Model.getMetaTypes().getUMLClass(), 
 134  
             "button.new-class",
 135  
             Model.getMetaTypes().getInterface(), 
 136  
             "button.new-interface",
 137  
             Model.getMetaTypes().getAttribute(), 
 138  
             "button.new-attribute",
 139  
             Model.getMetaTypes().getOperation(), 
 140  
             "button.new-operation",
 141  
             Model.getMetaTypes().getDataType(),
 142  
             "button.new-datatype",
 143  
             Model.getMetaTypes().getEnumeration(),
 144  
             "button.new-enumeration",
 145  
             Model.getMetaTypes().getEnumerationLiteral(),
 146  
             "button.new-enumeration-literal",
 147  
             Model.getMetaTypes().getSignal(),
 148  
             "button.new-signal",
 149  
             Model.getMetaTypes().getException(),
 150  
             "button.new-exception",
 151  
             Model.getMetaTypes().getComponent(), 
 152  
             "button.new-component",
 153  
             Model.getMetaTypes().getComponentInstance(), 
 154  
             "button.new-componentinstance",
 155  
             Model.getMetaTypes().getNode(), 
 156  
             "button.new-node",
 157  
             Model.getMetaTypes().getNodeInstance(), 
 158  
             "button.new-nodeinstance",
 159  
             Model.getMetaTypes().getReception(), 
 160  
             "button.new-reception",             
 161  
             Model.getMetaTypes().getStereotype(), 
 162  
             "button.new-stereotype" };
 163  
 
 164  
     /**
 165  
      * Creates a new instance of ExplorerPopup.
 166  
      *
 167  
      * @param selectedItem
 168  
      *            is the item that we are pointing at.
 169  
      * @param me
 170  
      *            is the event.
 171  
      */
 172  
     public ExplorerPopup(Object selectedItem, MouseEvent me) {
 173  0
         super("Explorer popup menu");
 174  
 
 175  
         /* Check if multiple items are selected. */
 176  0
         boolean multiSelect =
 177  
                 TargetManager.getInstance().getTargets().size() > 1;
 178  
 
 179  0
         boolean mutableModelElementsOnly = true;
 180  0
         for (Object element : TargetManager.getInstance().getTargets()) {
 181  0
             if (!Model.getFacade().isAUMLElement(element)
 182  
                     || Model.getModelManagementHelper().isReadOnly(element)) {
 183  0
                 mutableModelElementsOnly = false;
 184  0
                 break;
 185  
             }
 186  
         }
 187  
 
 188  0
         final ArgoDiagram activeDiagram = DiagramUtils.getActiveDiagram();
 189  
 
 190  
         // TODO: I've made some attempt to rationalize the conditions here
 191  
         // and make them more readable. However I'd suggest that the
 192  
         // conditions should move to each diagram.
 193  
         // Break up one complex method into a few simple ones and
 194  
         // give the diagrams more knowledge of themselves
 195  
         // (although the diagrams may in fact delegate this in
 196  
         // turn to the Model component).
 197  
         // Bob Tarling 31 Jan 2004
 198  
         // eg the code here should be something like -
 199  
         // if (activeDiagram.canAdd(selectedItem)) {
 200  
         // UMLAction action =
 201  
         // new ActionAddExistingNode(
 202  
         // menuLocalize("menu.popup.add-to-diagram"),
 203  
         // selectedItem);
 204  
         // action.setEnabled(action.shouldBeEnabled());
 205  
         // this.add(action);
 206  
         // }
 207  
 
 208  
         // profile section: dealing with profiles in different states
 209  
 
 210  
         // 1. a noneditable applied profile
 211  
         try {
 212  0
             if (!multiSelect && selectedItem instanceof Profile
 213  
                     && !((Profile) selectedItem).getProfilePackages().isEmpty()) {
 214  0
                 this.add(new ActionExportProfileXMI((Profile) selectedItem));
 215  
             }
 216  0
         } catch (Exception e) {
 217  
             // just no item added in this case
 218  0
         }
 219  
 
 220  
         // 2. the profile configuration, holding noneditable applied profiles
 221  0
         if (!multiSelect && selectedItem instanceof ProfileConfiguration) {
 222  0
             this.add(new ActionManageProfiles());
 223  
         }
 224  
 
 225  
         // 3. the editable unapplied profile
 226  
 
 227  0
         if (Model.getFacade().isAProfile(selectedItem)) {
 228  0
             this.add(new ActionDeployProfile(selectedItem));
 229  
         }
 230  
 
 231  
         // end of profile section
 232  
 
 233  0
         if (!multiSelect && mutableModelElementsOnly) {
 234  0
             initMenuCreateDiagrams();
 235  0
             this.add(createDiagrams);
 236  
         }
 237  
         
 238  0
         initMenuCreateModuleActions();
 239  
 
 240  0
         if (mutableModelElementsOnly) {
 241  0
             initMenuCreateModelElements();
 242  
         }
 243  
         
 244  0
         final boolean modelElementSelected = 
 245  
             Model.getFacade().isAUMLElement(selectedItem);
 246  
 
 247  0
         if (modelElementSelected) {
 248  0
             final boolean nAryAssociationSelected =
 249  
                 Model.getFacade().isANaryAssociation(selectedItem);
 250  0
             final boolean classifierSelected =
 251  
                 Model.getFacade().isAClassifier(selectedItem);
 252  0
             final boolean packageSelected =
 253  
                 Model.getFacade().isAPackage(selectedItem);
 254  0
             final boolean commentSelected =
 255  
                 Model.getFacade().isAComment(selectedItem);
 256  0
             final boolean stateVertexSelected =
 257  
                 Model.getFacade().isAStateVertex(selectedItem);
 258  0
             final boolean instanceSelected =
 259  
                 Model.getFacade().isAInstance(selectedItem);
 260  0
             final boolean dataValueSelected =
 261  
                 Model.getFacade().isADataValue(selectedItem);
 262  0
             final boolean relationshipSelected =
 263  
                 Model.getFacade().isARelationship(selectedItem);
 264  0
             final boolean flowSelected =
 265  
                 Model.getFacade().isAFlow(selectedItem);
 266  0
             final boolean linkSelected =
 267  
                 Model.getFacade().isALink(selectedItem);
 268  0
             final boolean transitionSelected =
 269  
                 Model.getFacade().isATransition(selectedItem);
 270  0
             final boolean activityDiagramActive =
 271  
                 activeDiagram instanceof UMLActivityDiagram;
 272  0
             final boolean sequenceDiagramActive =
 273  
                 activeDiagram instanceof SequenceDiagram;
 274  0
             final boolean stateDiagramActive =
 275  
                 activeDiagram instanceof UMLStateDiagram;
 276  0
             final Object selectedStateMachine =
 277  
                 (stateVertexSelected) ? Model
 278  
                     .getStateMachinesHelper().getStateMachine(selectedItem)
 279  
                     : null;
 280  0
             final Object diagramStateMachine =
 281  
                 (stateDiagramActive) ? ((UMLStateDiagram) activeDiagram)
 282  
                     .getStateMachine()
 283  
                     : null;
 284  0
             final Object diagramActivity =
 285  
                 (activityDiagramActive)
 286  
                     ? ((UMLActivityDiagram) activeDiagram).getStateMachine()
 287  
                     : null;
 288  
 
 289  0
             Collection projectModels = 
 290  
                 ProjectManager.getManager().getCurrentProject().getModels();
 291  0
             if (!multiSelect) {
 292  0
                 if ((classifierSelected && !relationshipSelected)
 293  
                         || (packageSelected 
 294  
                                 // TODO: Allow adding models to a diagram - issue 4172.
 295  
                                 && !projectModels.contains(selectedItem))
 296  
                         || (stateVertexSelected
 297  
                                 && activityDiagramActive
 298  
                                 && diagramActivity == selectedStateMachine)
 299  
                         || (stateVertexSelected
 300  
                                 && stateDiagramActive
 301  
                                 && diagramStateMachine == selectedStateMachine)
 302  
                         || (instanceSelected
 303  
                                 && !dataValueSelected
 304  
                                 && !sequenceDiagramActive)
 305  
                         || nAryAssociationSelected || commentSelected) {
 306  
                     // TODO: Why can't we use ActionAddExistingNodes here? Bob.
 307  0
                     Action action =
 308  
                         new ActionAddExistingNode(
 309  
                             menuLocalize("menu.popup.add-to-diagram"),
 310  
                             selectedItem);
 311  0
                     this.add(action);
 312  
                 }
 313  
 
 314  0
                 if ((relationshipSelected
 315  
                         && !flowSelected
 316  
                         && !nAryAssociationSelected)
 317  
                         || (linkSelected && !sequenceDiagramActive)
 318  
                         || transitionSelected) {
 319  
 
 320  0
                     Action action =
 321  
                         new ActionAddExistingEdge(
 322  
                             menuLocalize("menu.popup.add-to-diagram"),
 323  
                             selectedItem);
 324  0
                     this.add(action);
 325  0
                     addMenuItemForBothEndsOf(selectedItem);
 326  
                 }
 327  
 
 328  0
                 if (classifierSelected
 329  
                         || packageSelected) {
 330  0
                     this.add(new ActionSetSourcePath());
 331  
                 }
 332  
             }
 333  
 
 334  
 
 335  0
             if (mutableModelElementsOnly 
 336  
                     // Can't delete last top level model
 337  
                     && !(projectModels.size() == 1 
 338  
                             && projectModels.contains(selectedItem))) {
 339  
                 // TODO: Shouldn't be creating a new instance here. We should
 340  
                 // hold the delete action in some central place.
 341  0
                 this.add(new ActionDeleteModelElements());
 342  
             }
 343  
         }
 344  
         // TODO: Make sure this shouldn't go into a previous
 345  
         // condition -tml
 346  0
         if (!multiSelect) {
 347  0
             if (selectedItem instanceof UMLClassDiagram) {
 348  0
                 Action action =
 349  
                     new ActionAddAllClassesFromModel(
 350  
                         menuLocalize("menu.popup.add-all-classes-to-diagram"),
 351  
                         selectedItem);
 352  0
                 this.add(action);
 353  
             }
 354  
         }
 355  
 
 356  0
         if (multiSelect) {
 357  0
             List<Object> classifiers = new ArrayList<Object>();
 358  0
             for (Object o : TargetManager.getInstance().getTargets()) {
 359  
                 // TODO: Should be anything allowed by current diagram
 360  0
                 if (Model.getFacade().isAClassifier(o)
 361  
                         && !Model.getFacade().isARelationship(o)) {
 362  0
                     classifiers.add(o);
 363  
                 }
 364  
             }
 365  0
             if (!classifiers.isEmpty()) {
 366  0
                 Action action =
 367  
                     new ActionAddExistingNodes(
 368  
                         menuLocalize("menu.popup.add-to-diagram"),
 369  
                         classifiers);
 370  0
                 this.add(action);
 371  
             }
 372  0
         } else if (selectedItem instanceof Diagram) {
 373  0
             this.add(new ActionSaveDiagramToClipboard());
 374  
             // TODO: Delete should be available on any combination of model
 375  
             // elements and diagrams.
 376  
             // TODO: Shouldn't be creating a new instance here. We should
 377  
             // hold the delete action in some central place.
 378  0
             ActionDeleteModelElements ad = new ActionDeleteModelElements();
 379  0
             ad.setEnabled(ad.shouldBeEnabled());
 380  0
             this.add(ad);
 381  
         }
 382  0
     }
 383  
 
 384  
     /**
 385  
      * initialize the menu for diagram construction in the explorer popup menu.
 386  
      *
 387  
      */
 388  
     private void initMenuCreateDiagrams() {
 389  0
         createDiagrams.add(new ActionUseCaseDiagram());
 390  
 
 391  0
         createDiagrams.add(new ActionClassDiagram());
 392  
 
 393  0
         createDiagrams.add(new ActionSequenceDiagram());
 394  
 
 395  0
         createDiagrams.add(new ActionCollaborationDiagram());
 396  
 
 397  0
         createDiagrams.add(new ActionStateDiagram());
 398  
 
 399  0
         createDiagrams.add(new ActionActivityDiagram());
 400  
 
 401  0
         createDiagrams.add(new ActionDeploymentDiagram());
 402  0
     }
 403  
 
 404  
     /**
 405  
      * initialize the menu for diagram construction in the explorer popup menu.
 406  
      *
 407  
      */
 408  
     private void initMenuCreateModelElements() {
 409  0
         List targets = TargetManager.getInstance().getTargets();
 410  0
         Set<JMenuItem> menuItems = new TreeSet<JMenuItem>();
 411  0
         if (targets.size() >= 2) {
 412  
             // Check to see if all targets are classifiers
 413  
             // before adding an option to create an association between
 414  
             // them all
 415  0
             boolean classifierRoleFound = false;
 416  0
             boolean classifierRolesOnly = true;
 417  0
             for (Iterator it = targets.iterator();
 418  0
                     it.hasNext() && classifierRolesOnly; ) {
 419  0
                 if (Model.getFacade().isAClassifierRole(it.next())) {
 420  0
                     classifierRoleFound = true;
 421  
                 } else {
 422  0
                     classifierRolesOnly = false;
 423  
                 }
 424  
             }
 425  0
             if (classifierRolesOnly) {
 426  0
                 menuItems.add(new OrderedMenuItem(
 427  
                         new ActionCreateAssociationRole(
 428  
                                 Model.getMetaTypes().getAssociationRole(), 
 429  
                                 targets)));
 430  0
             } else if (!classifierRoleFound) {
 431  0
                 boolean classifiersOnly = true;
 432  0
                 for (Iterator it = targets.iterator();
 433  0
                         it.hasNext() && classifiersOnly; ) {
 434  0
                     if (!Model.getFacade().isAClassifier(it.next())) {
 435  0
                         classifiersOnly = false;
 436  
                     }
 437  
                 }
 438  0
                 if (classifiersOnly) {
 439  0
                     menuItems.add(new OrderedMenuItem(
 440  
                             new ActionCreateAssociation(
 441  
                                     Model.getMetaTypes().getAssociation(), 
 442  
                                     targets)));
 443  
                 }
 444  
             }
 445  
         }
 446  0
         if (targets.size() == 2) {
 447  0
             addCreateModelElementAction(
 448  
                     menuItems,
 449  
                     Model.getMetaTypes().getDependency(),
 450  
                     " " + menuLocalize("menu.popup.depends-on") + " ");
 451  
             
 452  0
             addCreateModelElementAction(
 453  
                     menuItems,
 454  
                     Model.getMetaTypes().getGeneralization(),
 455  
                     " " + menuLocalize("menu.popup.generalizes") + " ");
 456  0
             addCreateModelElementAction(
 457  
                     menuItems,
 458  
                     Model.getMetaTypes().getInclude(),
 459  
                     " " + menuLocalize("menu.popup.includes") + " ");
 460  0
             addCreateModelElementAction(
 461  
                     menuItems,
 462  
                     Model.getMetaTypes().getExtend(),
 463  
                     " " + menuLocalize("menu.popup.extends") + " ");
 464  0
             addCreateModelElementAction(
 465  
                     menuItems,
 466  
                     Model.getMetaTypes().getPackageImport(),
 467  
                     " " + menuLocalize("menu.popup.has-permission-on") + " ");
 468  0
             addCreateModelElementAction(
 469  
                     menuItems,
 470  
                     Model.getMetaTypes().getUsage(),
 471  
                     " " + menuLocalize("menu.popup.uses") + " ");
 472  0
             addCreateModelElementAction(
 473  
                     menuItems,
 474  
                     Model.getMetaTypes().getAbstraction(),
 475  
                     " " + menuLocalize("menu.popup.realizes") + " ");
 476  0
         } else if (targets.size() == 1) {
 477  
             
 478  0
             Object target = targets.get(0);
 479  
 
 480  
             // iterate through all possible model elements to determine which  
 481  
             // are valid to be contained by the selected target
 482  0
             int start = 0;
 483  0
             if (Model.getFacade().getUmlVersion().charAt(0) == '1') {
 484  
                 // skip profile item for UML1
 485  0
                 start = 2;
 486  
             }
 487  0
             for (int iter = start; iter < MODEL_ELEMENT_MENUITEMS.length; 
 488  0
                 iter += 2) {
 489  
                 
 490  0
                 Object me = MODEL_ELEMENT_MENUITEMS[iter];
 491  0
                 String md = (String) MODEL_ELEMENT_MENUITEMS[iter + 1];
 492  
                 
 493  
                 // test if this element can be contained by the target
 494  0
                 if (Model.getUmlFactory().isContainmentValid(me, target)) {
 495  
                     // this element can be contained add a menu item 
 496  
                     // that allows the user to take that action
 497  0
                     menuItems.add(new OrderedMenuItem(
 498  
                             new ActionCreateContainedModelElement(
 499  
                                     me, target, md)));
 500  
                 }
 501  
             }    
 502  
         }
 503  
         
 504  0
         if (menuItems.size() == 1) {
 505  0
             add(menuItems.iterator().next());
 506  0
         } else if (menuItems.size() > 1) {
 507  0
             JMenu menu =
 508  
                 new JMenu(menuLocalize("menu.popup.create-model-element"));
 509  0
             add(menu);
 510  0
             for (JMenuItem item : menuItems) {
 511  0
                 menu.add(item);
 512  
             }
 513  
         }
 514  0
     }
 515  
     
 516  
     private void initMenuCreateModuleActions() {
 517  0
         final List<Action> contextActions = 
 518  
             ContextActionFactoryManager.getContextPopupActions();
 519  0
         LOG.info(contextActions);
 520  0
         if (contextActions instanceof ActionList) {
 521  0
             recursiveAdd(this, (Action) contextActions);
 522  
         } else {
 523  0
             for (Action a : contextActions) {
 524  0
                 recursiveAdd(this, a);
 525  
             }
 526  
         }
 527  0
     }
 528  
     
 529  
     private void recursiveAdd(MenuElement menu, Action a) {
 530  0
         if (a instanceof List<?>) {
 531  0
             JMenu m = new JMenu(a);
 532  0
             if (menu instanceof JPopupMenu) {
 533  0
                 ((JPopupMenu) menu).add(m);
 534  0
             } else if (menu instanceof JMenu) {
 535  0
                 ((JMenu) menu).add(m);
 536  
             }
 537  0
             for (Action subAction : (List<Action>) a) {
 538  0
                 recursiveAdd(m, subAction);
 539  
             }
 540  0
         } else {
 541  0
             if (menu instanceof JPopupMenu) {
 542  0
                 ((JPopupMenu) menu).add(a);
 543  0
             } else if (menu instanceof JMenu) {
 544  0
                 ((JMenu) menu).add(a);
 545  
             }
 546  
         }
 547  0
     }
 548  
     
 549  
     private void addCreateModelElementAction(
 550  
                 Set<JMenuItem> menuItems,
 551  
                 Object metaType,
 552  
                 String relationshipDescr) {
 553  0
         List targets = TargetManager.getInstance().getTargets();
 554  0
         Object source = targets.get(0);
 555  0
         Object dest = targets.get(1);
 556  0
         JMenu subMenu = new OrderedMenu(
 557  
                 menuLocalize("menu.popup.create") + " "
 558  
                 + Model.getMetaTypes().getName(metaType));
 559  0
         buildDirectionalCreateMenuItem(
 560  
             metaType, dest, source, relationshipDescr, subMenu);
 561  0
         buildDirectionalCreateMenuItem(
 562  
             metaType, source, dest, relationshipDescr, subMenu);
 563  0
         if (subMenu.getMenuComponents().length > 0) {
 564  0
             menuItems.add(subMenu);
 565  
         }
 566  0
     }
 567  
     
 568  
     /**
 569  
      * Attempt to build a menu item to create the given model element type
 570  
      * as a relation betwen two existing model elements.
 571  
      * If succesful then the menu item is added to the given menu
 572  
      * @param metaType The type of model element the menu item should create
 573  
      * @param source The source model element
 574  
      * @param dest The destination model element
 575  
      * @param relationshipDescr A textual description that describes how
 576  
      *                          source relates to dest
 577  
      * @param menu The menu to which the menu item should be added
 578  
      */
 579  
     private void buildDirectionalCreateMenuItem(
 580  
             Object metaType, 
 581  
             Object source, 
 582  
             Object dest, 
 583  
             String relationshipDescr,
 584  
             JMenu menu) {
 585  0
         if (Model.getUmlFactory().isConnectionValid(
 586  
                     metaType, source, dest, true)) {
 587  0
             JMenuItem menuItem = new JMenuItem(
 588  
                     new ActionCreateEdgeModelElement(
 589  
                             metaType, 
 590  
                             source, 
 591  
                             dest, 
 592  
                             relationshipDescr));
 593  0
             if (menuItem != null) {
 594  0
                 menu.add(menuItem);
 595  
             }
 596  
         }
 597  0
     }
 598  
 
 599  
 
 600  
     /**
 601  
      * Localize a popup menu item in the navigator pane.
 602  
      *
 603  
      * @param key
 604  
      *            The key for the string to localize.
 605  
      * @return The localized string.
 606  
      */
 607  
     private String menuLocalize(String key) {
 608  0
         return Translator.localize(key);
 609  
     }
 610  
     
 611  
     /**
 612  
      * Add popup menu items for adding to diagram both edge ends.
 613  
      *
 614  
      * @param edge
 615  
      *            The edge for which the menu item will be added.
 616  
      */
 617  
     private void addMenuItemForBothEndsOf(Object edge) {
 618  0
         Collection coll = null;
 619  0
         if (Model.getFacade().isAAssociation(edge)
 620  
                 || Model.getFacade().isALink(edge)) {
 621  0
             coll = Model.getFacade().getConnections(edge);
 622  0
         } else if (Model.getFacade().isAAbstraction(edge)
 623  
                 || Model.getFacade().isADependency(edge)) {
 624  0
             coll = new ArrayList();
 625  0
             coll.addAll(Model.getFacade().getClients(edge));
 626  0
             coll.addAll(Model.getFacade().getSuppliers(edge));
 627  0
         } else if (Model.getFacade().isAGeneralization(edge)) {
 628  0
             coll = new ArrayList();
 629  0
             Object parent = Model.getFacade().getGeneral(edge);
 630  0
             coll.add(parent);
 631  0
             coll.addAll(Model.getFacade().getChildren(parent));
 632  
         }
 633  0
         if (coll == null) {
 634  0
             return;
 635  
         }
 636  0
         Iterator iter = coll.iterator();
 637  0
         while (iter.hasNext()) {
 638  0
             Object me = iter.next();
 639  0
             if (me != null) {
 640  0
                 if (Model.getFacade().isAAssociationEnd(me)) {
 641  0
                     me = Model.getFacade().getType(me);
 642  
                 }
 643  0
                 if (me != null) {
 644  0
                     String name = Model.getFacade().getName(me);
 645  0
                     if (name == null || name.length() == 0) {
 646  0
                         name = "(anon element)";
 647  
                     }
 648  0
                     Action action =
 649  
                         new ActionAddExistingRelatedNode(
 650  
                             menuLocalize("menu.popup.add-to-diagram") + ": "
 651  
                              + name,
 652  
                             me);
 653  0
                     this.add(action);
 654  
                 }
 655  
             }
 656  0
         }
 657  0
     }
 658  
 
 659  
     /**
 660  
      * The UID.
 661  
      */
 662  
     private static final long serialVersionUID = -5663884871599931780L;
 663  
 
 664  
     
 665  
     private class ActionAddExistingRelatedNode extends UndoableAction {
 666  
 
 667  
         /**
 668  
          * The UML object to be added to the diagram.
 669  
          */
 670  
         private Object object;
 671  
 
 672  
         /**
 673  
          * The Constructor.
 674  
          *
 675  
          * @param name the localized name of the action
 676  
          * @param o the node UML object to be added
 677  
          */
 678  0
         public ActionAddExistingRelatedNode(String name, Object o) {
 679  0
             super(name);
 680  0
             object = o;
 681  0
         }
 682  
 
 683  
         /**
 684  
          * @see javax.swing.Action#isEnabled()
 685  
          */
 686  
         public boolean isEnabled() {
 687  0
             ArgoDiagram dia = DiagramUtils.getActiveDiagram();
 688  0
             if (dia == null) {
 689  0
                 return false;
 690  
             }
 691  0
             MutableGraphModel gm = (MutableGraphModel) dia.getGraphModel();
 692  0
             return gm.canAddNode(object);
 693  
         }
 694  
         
 695  
         public void actionPerformed(ActionEvent ae) {
 696  0
             super.actionPerformed(ae);
 697  0
             Editor ce = Globals.curEditor();
 698  0
             GraphModel gm = ce.getGraphModel();
 699  0
             if (!(gm instanceof MutableGraphModel)) {
 700  0
                 return;
 701  
             }
 702  
 
 703  0
             String instructions = null;
 704  0
             if (object != null) {
 705  0
                 instructions =
 706  
                     Translator.localize(
 707  
                         "misc.message.click-on-diagram-to-add",
 708  
                         new Object[] {
 709  
                                 Model.getFacade().toString(object),
 710  
                         });
 711  0
                 Globals.showStatus(instructions);
 712  
             }
 713  
             
 714  0
             ArrayList<Object> elementsToAdd = new ArrayList<Object>(1);
 715  0
             elementsToAdd.add(object);
 716  0
             final ModeAddToDiagram placeMode =
 717  
                 new ModeAddToDiagram(elementsToAdd, instructions);
 718  
 
 719  0
             Globals.mode(placeMode, false);
 720  0
         }
 721  
     } /* end class ActionAddExistingRelatedNode */
 722  
     
 723  
     /**
 724  
      * A JMenuItem that will order by display name
 725  
      *
 726  
      * @author Bob Tarling
 727  
      */
 728  
     private class OrderedMenuItem extends JMenuItem implements Comparable {
 729  
         
 730  
         /**
 731  
          * Instantiate OrderedMenuItem
 732  
          * @param action
 733  
          */
 734  0
         public OrderedMenuItem(Action action) {
 735  0
             super(action);
 736  0
         }
 737  
 
 738  
         /**
 739  
          * Instantiate OrderedMenuItem
 740  
          * @param name
 741  
          */
 742  0
         public OrderedMenuItem(String name) {
 743  0
             super(name);
 744  0
             setName(name);
 745  0
         }
 746  
 
 747  
         public int compareTo(Object o) {
 748  0
             JMenuItem other = (JMenuItem) o;
 749  0
             return toString().compareTo(other.toString());
 750  
         }
 751  
     }
 752  
         
 753  
     /**
 754  
      * A JMenuItem that will order by display name
 755  
      *
 756  
      * @author Bob Tarling
 757  
      */
 758  
     private class OrderedMenu extends JMenu implements Comparable {
 759  
         
 760  
         /**
 761  
          * Instantiate OrderedMenu
 762  
          * @param name
 763  
          */
 764  0
         public OrderedMenu(String name) {
 765  0
             super(name);
 766  0
         }
 767  
 
 768  
         public int compareTo(Object o) {
 769  0
             JMenuItem other = (JMenuItem) o;
 770  0
             return toString().compareTo(other.toString());
 771  
         }
 772  
     }
 773  
         
 774  
     /**
 775  
      * An action to create an association between 2 or more model elements.
 776  
      *
 777  
      * @author Bob Tarling
 778  
      */
 779  
     private class ActionCreateAssociation extends AbstractAction {
 780  
         
 781  
         private Object metaType; 
 782  
         private List classifiers;
 783  
 
 784  
         public ActionCreateAssociation(
 785  
                 Object theMetaType, 
 786  0
                 List classifiersList) {
 787  0
             super(menuLocalize("menu.popup.create") + " "
 788  
                     + Model.getMetaTypes().getName(theMetaType));
 789  0
             this.metaType = theMetaType;
 790  0
             this.classifiers = classifiersList;
 791  0
         }
 792  
 
 793  
         public void actionPerformed(ActionEvent e) {
 794  
             try {
 795  0
                 Object newElement = Model.getUmlFactory().buildConnection(
 796  
                     metaType,
 797  
                     classifiers.get(0),
 798  
                     null,
 799  
                     classifiers.get(1),
 800  
                     null,
 801  
                     null,
 802  
                     null);
 803  0
                 for (int i = 2; i < classifiers.size(); ++i) {
 804  0
                     Model.getUmlFactory().buildConnection(
 805  
                             Model.getMetaTypes().getAssociationEnd(),
 806  
                             newElement,
 807  
                             null,
 808  
                             classifiers.get(i),
 809  
                             null,
 810  
                             null,
 811  
                             null);
 812  
                 }
 813  0
             } catch (IllegalModelElementConnectionException e1) {
 814  0
                 LOG.error("Exception", e1);
 815  0
             }
 816  0
         }
 817  
     }
 818  
     
 819  
     
 820  
     /**
 821  
      * An action to create an association between 2 or more model elements.
 822  
      *
 823  
      * @author Bob Tarling
 824  
      */
 825  
     private class ActionCreateAssociationRole extends AbstractAction {
 826  
 
 827  
         private Object metaType; 
 828  
         private List classifierRoles;
 829  
 
 830  
         public ActionCreateAssociationRole(
 831  
                 Object theMetaType, 
 832  0
                 List classifierRolesList) {
 833  0
             super(menuLocalize("menu.popup.create") + " "
 834  
                     + Model.getMetaTypes().getName(theMetaType));
 835  0
             this.metaType = theMetaType;
 836  0
             this.classifierRoles = classifierRolesList;
 837  0
         }
 838  
 
 839  
         public void actionPerformed(ActionEvent e) {
 840  
             try {
 841  0
                 Object newElement = Model.getUmlFactory().buildConnection(
 842  
                         metaType,
 843  
                         classifierRoles.get(0),
 844  
                         null,
 845  
                         classifierRoles.get(1),
 846  
                         null,
 847  
                         null,
 848  
                         null);
 849  0
                 for (int i = 2; i < classifierRoles.size(); ++i) {
 850  0
                     Model.getUmlFactory().buildConnection(
 851  
                             Model.getMetaTypes().getAssociationEndRole(),
 852  
                             newElement,
 853  
                             null,
 854  
                             classifierRoles.get(i),
 855  
                             null,
 856  
                             null,
 857  
                             null);
 858  
                 }
 859  0
             } catch (IllegalModelElementConnectionException e1) {
 860  0
                 LOG.error("Exception", e1);
 861  0
             }
 862  0
         }
 863  
     }
 864  
 }