| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| UMLMutableGraphSupport |
|
| 3.2962962962962963;3.296 |
| 1 | /* $Id: UMLMutableGraphSupport.java 17850 2010-01-12 19:53:35Z linus $ | |
| 2 | ***************************************************************************** | |
| 3 | * Copyright (c) 2009 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 | * tfmorris | |
| 11 | ***************************************************************************** | |
| 12 | * | |
| 13 | * Some portions of this file was previously release using the BSD License: | |
| 14 | */ | |
| 15 | ||
| 16 | // Copyright (c) 1996-2007 The Regents of the University of California. All | |
| 17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
| 18 | // software and its documentation without fee, and without a written | |
| 19 | // agreement is hereby granted, provided that the above copyright notice | |
| 20 | // and this paragraph appear in all copies. This software program and | |
| 21 | // documentation are copyrighted by The Regents of the University of | |
| 22 | // California. The software program and documentation are supplied "AS | |
| 23 | // IS", without any accompanying services from The Regents. The Regents | |
| 24 | // does not warrant that the operation of the program will be | |
| 25 | // uninterrupted or error-free. The end-user understands that the program | |
| 26 | // was developed for research purposes and is advised not to rely | |
| 27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
| 28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
| 29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
| 30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
| 31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
| 32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
| 33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| 34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
| 35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
| 36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
| 37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
| 38 | ||
| 39 | package org.argouml.uml.diagram; | |
| 40 | ||
| 41 | import java.util.ArrayList; | |
| 42 | import java.util.Collection; | |
| 43 | import java.util.Dictionary; | |
| 44 | import java.util.Iterator; | |
| 45 | import java.util.List; | |
| 46 | import java.util.Map; | |
| 47 | ||
| 48 | import org.apache.log4j.Logger; | |
| 49 | import org.argouml.kernel.Project; | |
| 50 | import org.argouml.model.DiDiagram; | |
| 51 | import org.argouml.model.Model; | |
| 52 | import org.argouml.model.UmlException; | |
| 53 | import org.argouml.uml.CommentEdge; | |
| 54 | import org.tigris.gef.base.Editor; | |
| 55 | import org.tigris.gef.base.Globals; | |
| 56 | import org.tigris.gef.base.Mode; | |
| 57 | import org.tigris.gef.base.ModeManager; | |
| 58 | import org.tigris.gef.graph.MutableGraphSupport; | |
| 59 | ||
| 60 | ||
| 61 | /** | |
| 62 | * UMLMutableGraphSupport is a helper class which extends | |
| 63 | * MutableGraphSupport to provide additional helper and common methods | |
| 64 | * for UML Diagrams. | |
| 65 | * | |
| 66 | * @author mkl@tigris.org | |
| 67 | * @since November 14, 2002, 10:20 PM | |
| 68 | */ | |
| 69 | public abstract class UMLMutableGraphSupport extends MutableGraphSupport { | |
| 70 | ||
| 71 | /** | |
| 72 | * Logger. | |
| 73 | */ | |
| 74 | 900 | private static final Logger LOG = |
| 75 | Logger.getLogger(UMLMutableGraphSupport.class); | |
| 76 | ||
| 77 | private DiDiagram diDiagram; | |
| 78 | ||
| 79 | /** | |
| 80 | * Contains all the nodes in the graphmodel/diagram. | |
| 81 | */ | |
| 82 | 2116 | private List nodes = new ArrayList(); |
| 83 | ||
| 84 | /** | |
| 85 | * Contains all the edges in the graphmodel/diagram. | |
| 86 | */ | |
| 87 | 2116 | private List edges = new ArrayList(); |
| 88 | ||
| 89 | /** | |
| 90 | * The owning namespace or "home model" of this diagram, not all | |
| 91 | * ModelElements in this graph are in the home model, but if they are added | |
| 92 | * and don't already have a model, they are placed in the "home model". | |
| 93 | * Also, elements from other models will have their FigNodes add a line to | |
| 94 | * say what their model is. | |
| 95 | */ | |
| 96 | private Object homeModel; | |
| 97 | ||
| 98 | /** | |
| 99 | * The project this graph model is in. | |
| 100 | */ | |
| 101 | private Project project; | |
| 102 | ||
| 103 | /** | |
| 104 | * Constructor. | |
| 105 | * | |
| 106 | * @see org.tigris.gef.graph.MutableGraphSupport | |
| 107 | */ | |
| 108 | public UMLMutableGraphSupport() { | |
| 109 | 2116 | super(); |
| 110 | 2116 | } |
| 111 | ||
| 112 | /** | |
| 113 | * Get all the nodes from the graphmodel/diagram. | |
| 114 | * | |
| 115 | * @see org.tigris.gef.graph.MutableGraphSupport#getNodes() | |
| 116 | * @return List of nodes in the graphmodel/diagram | |
| 117 | */ | |
| 118 | public List getNodes() { | |
| 119 | 148 | return nodes; |
| 120 | } | |
| 121 | ||
| 122 | /** | |
| 123 | * Get all the edges from the graphmodel/diagram. | |
| 124 | * | |
| 125 | * @return List of edges in the graphmodel/diagram | |
| 126 | */ | |
| 127 | public List getEdges() { | |
| 128 | 148 | return edges; |
| 129 | } | |
| 130 | ||
| 131 | /* | |
| 132 | * @see org.tigris.gef.graph.MutableGraphModel#containsNode(java.lang.Object) | |
| 133 | */ | |
| 134 | public boolean containsNode(Object node) { | |
| 135 | 0 | return nodes.contains(node); |
| 136 | } | |
| 137 | ||
| 138 | /** | |
| 139 | * @param edge the candidate edge | |
| 140 | * @return true if it is contained | |
| 141 | */ | |
| 142 | public boolean constainsEdge(Object edge) { | |
| 143 | 0 | return edges.contains(edge); |
| 144 | } | |
| 145 | ||
| 146 | /** | |
| 147 | * Remove a node from the diagram and notify GEF. | |
| 148 | * | |
| 149 | * @param node node to remove | |
| 150 | */ | |
| 151 | @Override | |
| 152 | public void removeNode(Object node) { | |
| 153 | 0 | if (!containsNode(node)) { |
| 154 | 0 | return; |
| 155 | } | |
| 156 | 0 | nodes.remove(node); |
| 157 | 0 | fireNodeRemoved(node); |
| 158 | 0 | } |
| 159 | ||
| 160 | /** | |
| 161 | * Remove an edge from the graphmodel and notify GEF. | |
| 162 | * | |
| 163 | * @param edge edge to remove | |
| 164 | */ | |
| 165 | @Override | |
| 166 | public void removeEdge(Object edge) { | |
| 167 | 0 | if (!containsEdge(edge)) { |
| 168 | 0 | return; |
| 169 | } | |
| 170 | 0 | edges.remove(edge); |
| 171 | 0 | fireEdgeRemoved(edge); |
| 172 | 0 | } |
| 173 | ||
| 174 | /** | |
| 175 | * Assume that anything can be connected to anything unless overridden | |
| 176 | * in a subclass. | |
| 177 | * | |
| 178 | * {@inheritDoc} | |
| 179 | */ | |
| 180 | public boolean canConnect(Object fromP, Object toP) { | |
| 181 | 0 | return true; |
| 182 | } | |
| 183 | ||
| 184 | ||
| 185 | /** | |
| 186 | * The connect method without specifying a connection | |
| 187 | * type is unavailable in the ArgoUML implmentation. | |
| 188 | * | |
| 189 | * {@inheritDoc} | |
| 190 | */ | |
| 191 | public Object connect(Object fromPort, Object toPort) { | |
| 192 | 0 | throw new UnsupportedOperationException( |
| 193 | "The connect method is not supported"); | |
| 194 | } | |
| 195 | ||
| 196 | /** | |
| 197 | * Get the namespace, also known as homemodel, which owns the diagram. | |
| 198 | * | |
| 199 | * @return the homemodel | |
| 200 | */ | |
| 201 | public Object getHomeModel() { | |
| 202 | 0 | return homeModel; |
| 203 | } | |
| 204 | ||
| 205 | /** | |
| 206 | * Set the namespace or homemodel of the diagram. This will become the | |
| 207 | * default namespace for any model elements which are created on | |
| 208 | * the diagram. | |
| 209 | * | |
| 210 | * @param ns the namespace | |
| 211 | */ | |
| 212 | public void setHomeModel(Object ns) { | |
| 213 | 2097 | if (!Model.getFacade().isANamespace(ns)) { |
| 214 | 0 | throw new IllegalArgumentException(); |
| 215 | } | |
| 216 | 2097 | homeModel = ns; |
| 217 | 2097 | } |
| 218 | ||
| 219 | /** | |
| 220 | * The connect method specifying a connection | |
| 221 | * type by class is unavailable in the ArgoUML implementation. | |
| 222 | * TODO: This should be unsupported. Use the 3 Object version | |
| 223 | * | |
| 224 | * {@inheritDoc} | |
| 225 | */ | |
| 226 | public Object connect(Object fromPort, Object toPort, Class edgeClass) { | |
| 227 | 0 | return connect(fromPort, toPort, (Object) edgeClass); |
| 228 | } | |
| 229 | ||
| 230 | /** | |
| 231 | * Construct and add a new edge of the given kind and connect | |
| 232 | * the given ports. | |
| 233 | * | |
| 234 | * @param fromPort The originating port to connect | |
| 235 | * | |
| 236 | * @param toPort The destination port to connect | |
| 237 | * | |
| 238 | * @param edgeType The type of edge to create. This is one of the types | |
| 239 | * returned by the methods of | |
| 240 | * <code>org.argouml.model.MetaTypes</code> | |
| 241 | * | |
| 242 | * @return The type of edge created (the same as | |
| 243 | * <code>edgeClass</code> if we succeeded, | |
| 244 | * <code>null</code> otherwise) | |
| 245 | */ | |
| 246 | public Object connect(Object fromPort, Object toPort, Object edgeType) { | |
| 247 | // If this was an association then there will be relevant | |
| 248 | // information to fetch out of the mode arguments. If it | |
| 249 | // not an association then these will be passed forward | |
| 250 | // harmlessly as null. | |
| 251 | 0 | Editor curEditor = Globals.curEditor(); |
| 252 | 0 | ModeManager modeManager = curEditor.getModeManager(); |
| 253 | 0 | Mode mode = modeManager.top(); |
| 254 | 0 | Dictionary args = mode.getArgs(); |
| 255 | 0 | Object style = args.get("aggregation"); //MAggregationKind |
| 256 | 0 | Boolean unidirectional = (Boolean) args.get("unidirectional"); |
| 257 | 0 | Object model = getProject().getModel(); |
| 258 | ||
| 259 | // Create the UML connection of the given type between the | |
| 260 | // given model elements. | |
| 261 | // default aggregation (none) | |
| 262 | 0 | Object connection = |
| 263 | buildConnection( | |
| 264 | edgeType, fromPort, style, toPort, | |
| 265 | null, unidirectional, | |
| 266 | model); | |
| 267 | ||
| 268 | 0 | if (connection == null) { |
| 269 | 0 | if (LOG.isDebugEnabled()) { |
| 270 | 0 | LOG.debug("Cannot make a " + edgeType |
| 271 | + " between a " + fromPort.getClass().getName() | |
| 272 | + " and a " + toPort.getClass().getName()); | |
| 273 | } | |
| 274 | 0 | return null; |
| 275 | } | |
| 276 | ||
| 277 | 0 | addEdge(connection); |
| 278 | 0 | if (LOG.isDebugEnabled()) { |
| 279 | 0 | LOG.debug("Connection type" + edgeType |
| 280 | + " made between a " + fromPort.getClass().getName() | |
| 281 | + " and a " + toPort.getClass().getName()); | |
| 282 | } | |
| 283 | 0 | return connection; |
| 284 | } | |
| 285 | ||
| 286 | /** | |
| 287 | * Construct and add a new edge of the given kind and connect | |
| 288 | * the given ports. | |
| 289 | * | |
| 290 | * @param fromPort The originating port to connect | |
| 291 | * | |
| 292 | * @param toPort The destination port to connect | |
| 293 | * | |
| 294 | * @param edgeType An indicator of the edge type to create. | |
| 295 | * | |
| 296 | * @param styleAttributes key/value pairs from which to style the edge. | |
| 297 | * | |
| 298 | * @return The type of edge created (the same as | |
| 299 | * <code>edgeClass</code> if we succeeded, | |
| 300 | * <code>null</code> otherwise) | |
| 301 | */ | |
| 302 | public Object connect(Object fromPort, Object toPort, Object edgeType, | |
| 303 | Map styleAttributes) { | |
| 304 | 0 | return null; |
| 305 | } | |
| 306 | ||
| 307 | ||
| 308 | /* | |
| 309 | * @see org.tigris.gef.graph.MutableGraphModel#canAddNode(java.lang.Object) | |
| 310 | */ | |
| 311 | public boolean canAddNode(Object node) { | |
| 312 | 0 | if (node == null) { |
| 313 | 0 | return false; |
| 314 | } | |
| 315 | 0 | if (Model.getFacade().isAComment(node)) { |
| 316 | 0 | return true; |
| 317 | } | |
| 318 | 0 | return false; |
| 319 | } | |
| 320 | ||
| 321 | /** | |
| 322 | * Return the source end of an edge. | |
| 323 | * | |
| 324 | * @param edge The edge for which we want the source port. | |
| 325 | * | |
| 326 | * @return The source port for the edge, or <code>null</code> if the | |
| 327 | * edge given is of the wrong type or has no source defined. | |
| 328 | */ | |
| 329 | public Object getSourcePort(Object edge) { | |
| 330 | ||
| 331 | 0 | if (edge instanceof CommentEdge) { |
| 332 | 0 | return ((CommentEdge) edge).getSource(); |
| 333 | 0 | } else if (Model.getFacade().isARelationship(edge) |
| 334 | || Model.getFacade().isATransition(edge) | |
| 335 | || Model.getFacade().isAAssociationEnd(edge)) { | |
| 336 | 0 | return Model.getUmlHelper().getSource(edge); |
| 337 | 0 | } else if (Model.getFacade().isALink(edge)) { |
| 338 | 0 | return Model.getCommonBehaviorHelper().getSource(edge); |
| 339 | } | |
| 340 | ||
| 341 | // Don't know what to do otherwise | |
| 342 | ||
| 343 | 0 | LOG.error(this.getClass().toString() + ": getSourcePort(" |
| 344 | + edge.toString() + ") - can't handle"); | |
| 345 | ||
| 346 | 0 | return null; |
| 347 | } | |
| 348 | ||
| 349 | ||
| 350 | /** | |
| 351 | * Return the destination end of an edge. | |
| 352 | * | |
| 353 | * @param edge The edge for which we want the destination port. | |
| 354 | * | |
| 355 | * @return The destination port for the edge, or <code>null</code> if | |
| 356 | * the edge given is otf the wrong type or has no destination | |
| 357 | * defined. | |
| 358 | */ | |
| 359 | public Object getDestPort(Object edge) { | |
| 360 | 0 | if (edge instanceof CommentEdge) { |
| 361 | 0 | return ((CommentEdge) edge).getDestination(); |
| 362 | 0 | } else if (Model.getFacade().isAAssociation(edge)) { |
| 363 | 0 | List conns = new ArrayList(Model.getFacade().getConnections(edge)); |
| 364 | 0 | return conns.get(1); |
| 365 | 0 | } else if (Model.getFacade().isARelationship(edge) |
| 366 | || Model.getFacade().isATransition(edge) | |
| 367 | || Model.getFacade().isAAssociationEnd(edge)) { | |
| 368 | 0 | return Model.getUmlHelper().getDestination(edge); |
| 369 | 0 | } else if (Model.getFacade().isALink(edge)) { |
| 370 | 0 | return Model.getCommonBehaviorHelper().getDestination(edge); |
| 371 | } | |
| 372 | ||
| 373 | // Don't know what to do otherwise | |
| 374 | ||
| 375 | 0 | LOG.error(this.getClass().toString() + ": getDestPort(" |
| 376 | + edge.toString() + ") - can't handle"); | |
| 377 | ||
| 378 | 0 | return null; |
| 379 | } | |
| 380 | ||
| 381 | ||
| 382 | /* | |
| 383 | * @see org.tigris.gef.graph.MutableGraphModel#canAddEdge(java.lang.Object) | |
| 384 | */ | |
| 385 | public boolean canAddEdge(Object edge) { | |
| 386 | 0 | if (edge instanceof CommentEdge) { |
| 387 | 0 | CommentEdge ce = (CommentEdge) edge; |
| 388 | 0 | return isConnectionValid(CommentEdge.class, |
| 389 | ce.getSource(), | |
| 390 | ce.getDestination()); | |
| 391 | 0 | } else if (edge != null |
| 392 | && Model.getUmlFactory().isConnectionType(edge)) { | |
| 393 | 0 | return isConnectionValid(edge.getClass(), |
| 394 | Model.getUmlHelper().getSource(edge), | |
| 395 | Model.getUmlHelper().getDestination(edge)); | |
| 396 | } | |
| 397 | 0 | return false; |
| 398 | } | |
| 399 | ||
| 400 | /* | |
| 401 | * @see org.tigris.gef.graph.MutableGraphModel#addNodeRelatedEdges(java.lang.Object) | |
| 402 | */ | |
| 403 | public void addNodeRelatedEdges(Object node) { | |
| 404 | 0 | if (Model.getFacade().isAModelElement(node)) { |
| 405 | 0 | List specs = |
| 406 | new ArrayList(Model.getFacade().getClientDependencies(node)); | |
| 407 | 0 | specs.addAll(Model.getFacade().getSupplierDependencies(node)); |
| 408 | 0 | Iterator iter = specs.iterator(); |
| 409 | 0 | while (iter.hasNext()) { |
| 410 | 0 | Object dependency = iter.next(); |
| 411 | 0 | if (canAddEdge(dependency)) { |
| 412 | 0 | addEdge(dependency); |
| 413 | // return; | |
| 414 | } | |
| 415 | 0 | } |
| 416 | } | |
| 417 | ||
| 418 | // Commentlinks for comments. Iterate over all the comment links | |
| 419 | // to find the comment and annotated elements. | |
| 420 | ||
| 421 | 0 | Collection cmnt = new ArrayList(); |
| 422 | 0 | if (Model.getFacade().isAComment(node)) { |
| 423 | 0 | cmnt.addAll(Model.getFacade().getAnnotatedElements(node)); |
| 424 | } | |
| 425 | // TODO: Comments are on Element in UML 2.x | |
| 426 | 0 | if (Model.getFacade().isAModelElement(node)) { |
| 427 | 0 | cmnt.addAll(Model.getFacade().getComments(node)); |
| 428 | } | |
| 429 | 0 | Iterator iter = cmnt.iterator(); |
| 430 | 0 | while (iter.hasNext()) { |
| 431 | 0 | Object ae = iter.next(); |
| 432 | 0 | CommentEdge ce = new CommentEdge(node, ae); |
| 433 | 0 | if (canAddEdge(ce)) { |
| 434 | 0 | addEdge(ce); |
| 435 | } | |
| 436 | 0 | } |
| 437 | 0 | } |
| 438 | ||
| 439 | /** | |
| 440 | * Create an edge of the given type and connect it to the | |
| 441 | * given nodes. | |
| 442 | * | |
| 443 | * @param edgeType the UML object type of the connection | |
| 444 | * @param fromElement the UML object for the "from" element | |
| 445 | * @param fromStyle the aggregationkind for the connection | |
| 446 | * in case of an association | |
| 447 | * @param toElement the UML object for the "to" element | |
| 448 | * @param toStyle the aggregationkind for the connection | |
| 449 | * in case of an association | |
| 450 | * @param unidirectional for association and associationrole | |
| 451 | * @param namespace the namespace to use if it can't be determined | |
| 452 | * @return the newly build connection (UML object) | |
| 453 | */ | |
| 454 | protected Object buildConnection( | |
| 455 | Object edgeType, | |
| 456 | Object fromElement, | |
| 457 | Object fromStyle, | |
| 458 | Object toElement, | |
| 459 | Object toStyle, | |
| 460 | Object unidirectional, | |
| 461 | Object namespace) { | |
| 462 | ||
| 463 | 0 | Object connection = null; |
| 464 | 0 | if (edgeType == CommentEdge.class) { |
| 465 | 0 | connection = |
| 466 | buildCommentConnection(fromElement, toElement); | |
| 467 | } else { | |
| 468 | try { | |
| 469 | 0 | connection = |
| 470 | Model.getUmlFactory().buildConnection( | |
| 471 | edgeType, | |
| 472 | fromElement, | |
| 473 | fromStyle, | |
| 474 | toElement, | |
| 475 | toStyle, | |
| 476 | unidirectional, | |
| 477 | namespace); | |
| 478 | 0 | LOG.info("Created " + connection + " between " |
| 479 | + fromElement + " and " + toElement); | |
| 480 | 0 | } catch (UmlException ex) { |
| 481 | // fail silently as we expect users to accidentally drop | |
| 482 | // on to wrong component | |
| 483 | 0 | } catch (IllegalArgumentException iae) { |
| 484 | // idem, e.g. for a generalization with leaf/root object | |
| 485 | // TODO: but showing the message in the statusbar would help | |
| 486 | // TODO: IllegalArgumentException should not be used for | |
| 487 | // events we expect to happen. We need a different way of | |
| 488 | // catching well-formedness rules. | |
| 489 | 0 | LOG.warn("IllegalArgumentException caught", iae); |
| 490 | 0 | } |
| 491 | } | |
| 492 | 0 | return connection; |
| 493 | } | |
| 494 | ||
| 495 | /** | |
| 496 | * Builds the model behind a connection between a comment and | |
| 497 | * the annotated modelelement. | |
| 498 | * | |
| 499 | * @param from The comment or annotated element. | |
| 500 | * @param to The comment or annotated element. | |
| 501 | * @return A commentEdge representing the model behind the connection | |
| 502 | * between a comment and an annotated modelelement. | |
| 503 | */ | |
| 504 | public CommentEdge buildCommentConnection(Object from, Object to) { | |
| 505 | 0 | if (from == null || to == null) { |
| 506 | 0 | throw new IllegalArgumentException("Either fromNode == null " |
| 507 | + "or toNode == null"); | |
| 508 | } | |
| 509 | 0 | Object comment = null; |
| 510 | 0 | Object annotatedElement = null; |
| 511 | 0 | if (Model.getFacade().isAComment(from)) { |
| 512 | 0 | comment = from; |
| 513 | 0 | annotatedElement = to; |
| 514 | } else { | |
| 515 | 0 | if (Model.getFacade().isAComment(to)) { |
| 516 | 0 | comment = to; |
| 517 | 0 | annotatedElement = from; |
| 518 | } else { | |
| 519 | 0 | return null; |
| 520 | } | |
| 521 | } | |
| 522 | ||
| 523 | 0 | CommentEdge connection = new CommentEdge(from, to); |
| 524 | 0 | Model.getCoreHelper().addAnnotatedElement(comment, annotatedElement); |
| 525 | 0 | return connection; |
| 526 | ||
| 527 | } | |
| 528 | ||
| 529 | /** | |
| 530 | * Checks if some type of edge is valid to connect two | |
| 531 | * types of node. | |
| 532 | * | |
| 533 | * @param edgeType the UML object type of the connection | |
| 534 | * @param fromElement the UML object type of the "from" | |
| 535 | * @param toElement the UML object type of the "to" | |
| 536 | * @return true if valid | |
| 537 | */ | |
| 538 | protected boolean isConnectionValid( | |
| 539 | Object edgeType, | |
| 540 | Object fromElement, | |
| 541 | Object toElement) { | |
| 542 | ||
| 543 | 0 | if (!nodes.contains(fromElement) || !nodes.contains(toElement)) { |
| 544 | // The connection is not valid unless both nodes are | |
| 545 | // in this graph model. | |
| 546 | 0 | return false; |
| 547 | } | |
| 548 | ||
| 549 | 0 | if (edgeType.equals(CommentEdge.class)) { |
| 550 | 0 | return ((Model.getFacade().isAComment(fromElement) |
| 551 | && Model.getFacade().isAModelElement(toElement)) | |
| 552 | || (Model.getFacade().isAComment(toElement) | |
| 553 | && Model.getFacade().isAModelElement(fromElement))); | |
| 554 | } | |
| 555 | 0 | return Model.getUmlFactory().isConnectionValid( |
| 556 | edgeType, | |
| 557 | fromElement, | |
| 558 | toElement, | |
| 559 | true); | |
| 560 | } | |
| 561 | ||
| 562 | /** | |
| 563 | * Package scope. Only the factory is supposed to set this. | |
| 564 | * @param dd | |
| 565 | */ | |
| 566 | void setDiDiagram(DiDiagram dd) { | |
| 567 | 0 | diDiagram = dd; |
| 568 | 0 | } |
| 569 | ||
| 570 | /** | |
| 571 | * Get the object that represents this diagram | |
| 572 | * in the DiagramInterchangeModel. | |
| 573 | * | |
| 574 | * @return the Diagram Interchange Diagram. | |
| 575 | */ | |
| 576 | public DiDiagram getDiDiagram() { | |
| 577 | 0 | return diDiagram; |
| 578 | } | |
| 579 | ||
| 580 | /** | |
| 581 | * Return true if the current targets may be removed from the diagram. | |
| 582 | * | |
| 583 | * @param figs a collection with the selected figs | |
| 584 | * @return true if the targets may be removed | |
| 585 | */ | |
| 586 | public boolean isRemoveFromDiagramAllowed(Collection figs) { | |
| 587 | 836 | return !figs.isEmpty(); |
| 588 | } | |
| 589 | ||
| 590 | /** | |
| 591 | * Set the project that the graph model is inside. | |
| 592 | * @param p the project | |
| 593 | */ | |
| 594 | public void setProject(Project p) { | |
| 595 | 2116 | project = p; |
| 596 | 2116 | } |
| 597 | ||
| 598 | /** | |
| 599 | * Get the project that the graph model is inside. | |
| 600 | * @return the project | |
| 601 | */ | |
| 602 | public Project getProject() { | |
| 603 | 0 | return project; |
| 604 | } | |
| 605 | } |