Coverage Report - org.argouml.uml.StereotypeUtility
 
Classes in this File Line Coverage Branch Coverage Complexity
StereotypeUtility
0%
0/147
0%
0/108
5.4
 
 1  
 /* $Id: StereotypeUtility.java 18880 2010-12-05 12:14:21Z thn $
 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  
  *    thn
 11  
  *****************************************************************************
 12  
  *
 13  
  * Some portions of this file was previously release using the BSD License:
 14  
  */
 15  
 
 16  
 // Copyright (c) 1996-2009 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;
 40  
 
 41  
 import java.util.ArrayList;
 42  
 import java.util.Collection;
 43  
 import java.util.HashSet;
 44  
 import java.util.Iterator;
 45  
 import java.util.List;
 46  
 import java.util.Set;
 47  
 import java.util.TreeSet;
 48  
 
 49  
 import javax.swing.Action;
 50  
 
 51  
 import org.argouml.kernel.Project;
 52  
 import org.argouml.kernel.ProjectManager;
 53  
 import org.argouml.model.Model;
 54  
 import org.argouml.uml.util.PathComparator;
 55  
 import org.argouml.util.MyTokenizer;
 56  
 
 57  
 /**
 58  
  * Utility classes for use in diagram popup menus for stereotypes.
 59  
  */
 60  
 public class StereotypeUtility {
 61  
 
 62  
     /**
 63  
      * Private default constructor.
 64  
      */
 65  
     private StereotypeUtility() {
 66  0
         super();
 67  0
     }
 68  
 
 69  
     /**
 70  
      * Returns an array of all applicable actions for adding stereotypes
 71  
      * for a given model element.
 72  
      * 
 73  
      * @param modelElement the given model element
 74  
      * @return the array with actions for adding stereotype UML objects
 75  
      */
 76  
     public static Action[] getApplyStereotypeActions(Object modelElement) {
 77  0
         Set availableStereotypes = getAvailableStereotypes(modelElement);
 78  
         
 79  0
         if (!availableStereotypes.isEmpty()) {
 80  0
             Action[] menuActions = new Action[availableStereotypes.size()];
 81  
 
 82  0
             Iterator it = availableStereotypes.iterator();
 83  0
             for (int i = 0; it.hasNext(); ++i) {
 84  0
                 menuActions[i] = new ActionAddStereotype(modelElement, 
 85  
                         it.next());
 86  
             }
 87  0
             return menuActions;
 88  
         }
 89  0
         return new Action[0];
 90  
     }
 91  
 
 92  
     /**
 93  
      * Returns an array of all applicable actions for adding stereotypes
 94  
      * for a given collection of model elements.
 95  
      * 
 96  
      * @param elements the given collection of model elements
 97  
      * @return the array with actions for adding stereotype UML objects
 98  
      */
 99  
     public static Action[] getApplyStereotypeActions(Collection elements) {
 100  0
         Set availableStereotypes = getAvailableStereotypes(elements);
 101  
         
 102  0
         if (!availableStereotypes.isEmpty()) {
 103  0
             Action[] menuActions = new Action[availableStereotypes.size()];
 104  
 
 105  0
             Iterator it = availableStereotypes.iterator();
 106  0
             for (int i = 0; it.hasNext(); ++i) {
 107  0
                 menuActions[i] = new ActionAddStereotype(elements, 
 108  
                         it.next());
 109  
             }
 110  0
             return menuActions;
 111  
         }
 112  0
         return new Action[0];
 113  
     }
 114  
 
 115  
     /**
 116  
      * Returns a set of all unique applicable stereotypes 
 117  
      * for a given modelelement.
 118  
      * 
 119  
      * @param modelElement the given modelelement
 120  
      * @return the set with stereotype UML objects
 121  
      */
 122  
     public static Set<Object> getAvailableStereotypes(Object modelElement) {
 123  0
         Set<List> paths = new HashSet<List>();
 124  0
         Set<Object> availableStereotypes = 
 125  
             new TreeSet<Object>(new PathComparator());
 126  0
         Collection models =
 127  
             ProjectManager.getManager().getCurrentProject().getModels();
 128  
         
 129  0
         Collection topLevelModels =
 130  
             ProjectManager.getManager().getCurrentProject().getModels();
 131  
         
 132  
         // adds all stereotypes defined at the top level namespaces        
 133  0
         Collection topLevelStereotypes = getTopLevelStereotypes(topLevelModels);
 134  
         
 135  0
         Collection validTopLevelStereotypes = new ArrayList();
 136  
             
 137  0
         addAllUniqueModelElementsFrom(availableStereotypes, paths, Model
 138  
                 .getExtensionMechanismsHelper().getAllPossibleStereotypes(
 139  
                         models, modelElement));
 140  0
         for (Object stereotype : topLevelStereotypes) {
 141  0
             if (Model.getExtensionMechanismsHelper().isValidStereotype(
 142  
                     modelElement, stereotype)) {
 143  0
                 validTopLevelStereotypes.add(stereotype);
 144  
             }            
 145  
         }
 146  
 
 147  0
         addAllUniqueModelElementsFrom(availableStereotypes, paths,
 148  
                 validTopLevelStereotypes);
 149  
         
 150  
         // adds all stereotypes defined at the profiles applied to the
 151  
         // current namespace
 152  0
         Object namespace = Model.getFacade().getNamespace(modelElement);
 153  0
         if (namespace != null) {
 154  
             while (true) {
 155  0
                 getApplicableStereotypesInNamespace(modelElement, paths,
 156  
                         availableStereotypes, namespace);
 157  0
                 Object newNamespace = Model.getFacade().getNamespace(namespace);
 158  
 
 159  0
                 if (newNamespace == null) {
 160  0
                     break;
 161  
                 }
 162  
 
 163  0
                 namespace = newNamespace;
 164  0
             }
 165  
         }
 166  
         
 167  
         // adds all stereotypes defined at the profiles applied 
 168  
         // to the current project
 169  0
         addAllUniqueModelElementsFrom(availableStereotypes, paths,
 170  
                 ProjectManager.getManager().getCurrentProject()
 171  
                         .getProfileConfiguration()
 172  
                         .findAllStereotypesForModelElement(modelElement));
 173  
         
 174  0
         return availableStereotypes;
 175  
     }
 176  
 
 177  
     /**
 178  
      * Returns a set (union) of all unique applicable stereotypes 
 179  
      * for a given collection of model elements.
 180  
      * TODO: This is not optimized for performance.
 181  
      * 
 182  
      * @param elements the given collection of model elements
 183  
      * @return the set with stereotype UML objects
 184  
      */
 185  
     public static Set<Object> getAvailableStereotypes(Collection elements) {
 186  0
         Set<Object> availableStereotypes = 
 187  
             new TreeSet<Object>(new PathComparator());
 188  0
         if (elements != null) {
 189  0
             for (Object element : elements) {
 190  0
                 availableStereotypes.addAll(getAvailableStereotypes(element));
 191  
             }
 192  
         }
 193  0
         return availableStereotypes;
 194  
     }
 195  
 
 196  
     private static Collection<Object> getTopLevelStereotypes(
 197  
             Collection<Object> topLevelModels) {
 198  0
         Collection<Object> ret = new ArrayList<Object>();
 199  0
         for (Object model : topLevelModels) {
 200  0
             for (Object stereotype : Model.getExtensionMechanismsHelper()
 201  
                     .getStereotypes(model)) {
 202  0
                 Object namespace = Model.getFacade().getNamespace(stereotype);
 203  0
                 if (Model.getFacade().getNamespace(namespace) == null) {
 204  0
                     ret.add(stereotype);
 205  
                 }
 206  0
             }
 207  
         }
 208  0
         return ret;
 209  
     }
 210  
     
 211  
     private static void getApplicableStereotypesInNamespace(
 212  
             Object modelElement, Set<List> paths,
 213  
             Set<Object> availableStereotypes, Object namespace) {
 214  
         
 215  0
         Collection allProfiles = getAllProfilePackages(Model.getFacade()
 216  
                 .getRoot(modelElement));
 217  0
         Collection<Object> allAppliedProfiles = new ArrayList<Object>();
 218  
         
 219  0
         for (Object profilePackage : allProfiles) {
 220  0
             Collection allDependencies = Model.getCoreHelper().getDependencies(
 221  
                     profilePackage, namespace);
 222  
 
 223  0
             for (Object dependency : allDependencies) {
 224  0
                 if (Model.getExtensionMechanismsHelper().hasStereotype(
 225  
                         dependency, "appliedProfile")) {
 226  0
                     allAppliedProfiles.add(profilePackage);
 227  0
                     break;
 228  
                 }
 229  
             }
 230  0
         }
 231  
         
 232  0
         addAllUniqueModelElementsFrom(availableStereotypes, paths,
 233  
                 getApplicableStereotypes(modelElement, allAppliedProfiles));
 234  0
     }
 235  
     
 236  
     private static Collection<Object> getApplicableStereotypes(
 237  
             Object modelElement, Collection<Object> allAppliedProfiles) {
 238  0
         Collection<Object> ret = new ArrayList<Object>();
 239  0
         for (Object profile : allAppliedProfiles) {
 240  0
             for (Object stereotype : Model.getExtensionMechanismsHelper()
 241  
                     .getStereotypes(profile)) {
 242  0
                 if (Model.getExtensionMechanismsHelper().isValidStereotype(
 243  
                         modelElement, stereotype)) {
 244  0
                     ret.add(stereotype);
 245  
                 }
 246  
             }
 247  
         }
 248  
 
 249  0
         return ret;
 250  
     }
 251  
 
 252  
     private static Collection<Object> getAllProfilePackages(Object model) {
 253  0
         Collection col = Model.getModelManagementHelper()
 254  
                 .getAllModelElementsOfKind(model,
 255  
                         Model.getMetaTypes().getPackage());
 256  0
         Collection<Object> ret = new ArrayList<Object>();
 257  
         
 258  0
         for (Object element : col) {
 259  0
             if (Model.getFacade().isAPackage(element)
 260  
                     && Model.getExtensionMechanismsHelper().hasStereotype(
 261  
                             element, "profile")) {
 262  0
                 ret.add(element);
 263  
             }
 264  
         }
 265  0
         return ret;
 266  
     }
 267  
 
 268  
     /**
 269  
      * Helper method for buildModelList.
 270  
      * <p>
 271  
      * Adds those elements from source that do not have the same path as any
 272  
      * path in paths to elements, and its path to paths. Thus elements will
 273  
      * never contain two objects with the same path, unless they are added by
 274  
      * other means.
 275  
      */
 276  
     private static void addAllUniqueModelElementsFrom(Set<Object> elements,
 277  
             Set<List> paths, Collection<Object> source) {
 278  0
         for (Object obj : source) {
 279  0
             List path = Model.getModelManagementHelper().getPathList(obj);
 280  0
             if (!paths.contains(path)) {
 281  0
                 paths.add(path);
 282  0
                 elements.add(obj);
 283  
             }
 284  0
         }
 285  0
     }
 286  
 
 287  
     /**
 288  
      * Replace the previous set of stereotypes applied to the given modelelement
 289  
      * with a new set, given in the form of a "," separated string of stereotype
 290  
      * names.
 291  
      * 
 292  
      * @param element the UML element to modify
 293  
      * @param stereotype Comma separated list of stereotype names. Empty string
 294  
      *                or <code>null</code> represents no stereotypes.
 295  
      * @param removeCurrent true if all current stereotypes should be removed
 296  
      *                before adding the new stereotypes, false if new
 297  
      *                stereotypes should be added to existing ones.
 298  
      */
 299  
     public static void dealWithStereotypes(Object element,
 300  
             StringBuilder stereotype, boolean removeCurrent) {
 301  0
         if (stereotype == null) {
 302  0
             dealWithStereotypes(element, (String) null, removeCurrent);
 303  
         } else {
 304  0
             dealWithStereotypes(element, stereotype.toString(), removeCurrent);
 305  
         }
 306  0
     }
 307  
 
 308  
     /**
 309  
      * This function shall replace the previous set of stereotypes of the given
 310  
      * modelelement with a new set, given in the form of a "," separated string
 311  
      * of stereotype names.
 312  
      * 
 313  
      * @param umlobject the UML element to adapt
 314  
      * @param stereotype Comma separated list stereotype names. Empty string or
 315  
      *                <code>null</code> represents no stereotypes.
 316  
      * @param full false if stereotypes are only added, true if removal should
 317  
      *                be done, too.
 318  
      */
 319  
     public static void dealWithStereotypes(Object umlobject, String stereotype,
 320  
             boolean full) {
 321  
         String token;
 322  
         MyTokenizer mst;
 323  0
         Collection<String> stereotypes = new ArrayList<String>();
 324  
 
 325  
         /* Convert the string (e.g. "aaa,bbb,ccc")
 326  
          * into separate stereotype-names (e.g. "aaa", "bbb", "ccc").
 327  
          */
 328  0
         if (stereotype != null) {
 329  0
             mst = new MyTokenizer(stereotype, " ,\\,");
 330  0
             while (mst.hasMoreTokens()) {
 331  0
                 token = mst.nextToken();
 332  0
                 if (!",".equals(token) && !" ".equals(token)) {
 333  0
                     stereotypes.add(token);
 334  
                 }
 335  
             }
 336  
         }
 337  
 
 338  0
         if (full) {
 339  
             // collect the to be removed stereotypes
 340  0
             Collection<Object> toBeRemoved = new ArrayList<Object>();
 341  0
             for (Object stereo : Model.getFacade().getStereotypes(umlobject)) {
 342  0
                 String stereotypename = Model.getFacade().getName(stereo);
 343  0
                 if (stereotypename != null
 344  
                         && !stereotypes.contains(stereotypename)) {
 345  0
                     toBeRemoved.add(getStereotype(umlobject, stereotypename));
 346  
                 }
 347  0
             }
 348  
 
 349  
             // and now remove them
 350  0
             for (Object o : toBeRemoved) {
 351  0
                 Model.getCoreHelper().removeStereotype(umlobject, o);
 352  
             }
 353  
         }
 354  
 
 355  
         // add stereotypes
 356  0
         for (String stereotypename : stereotypes) {
 357  0
             if (!Model.getExtensionMechanismsHelper()
 358  
                     .hasStereotype(umlobject, stereotypename)) {
 359  0
                 Object umlstereo = getStereotype(umlobject, stereotypename);
 360  0
                 if (umlstereo != null) {
 361  0
                     Model.getCoreHelper().addStereotype(umlobject, umlstereo);
 362  
                 }
 363  0
             }
 364  
         }
 365  0
         ProjectManager.getManager().updateRoots();
 366  0
     }
 367  
 
 368  
     /**
 369  
      * Finds a stereotype with the given name either in the user model, or in
 370  
      * one of the profiles' models.  If it's not found, a new stereotype will
 371  
      * be created in the root model.
 372  
      * 
 373  
      * @param obj A ModelElement to find a suitable stereotype for.
 374  
      * @param name The name of the stereotype to search for.
 375  
      * @return A stereotype named name, or possibly null.
 376  
      */
 377  
     private static Object getStereotype(Object obj, String name) {
 378  0
         Object root = Model.getFacade().getRoot(obj);
 379  
         Object stereo;
 380  
 
 381  0
         stereo = findStereotypeContained(obj, root, name);
 382  
         // TODO: The following rather than the above is probably the correct
 383  
         // way to search
 384  
 //        stereo = findStereotype(obj, null, name);
 385  0
         if (stereo != null) {
 386  0
             return stereo;
 387  
         }
 388  
 
 389  0
         Project project = ProjectManager.getManager().getCurrentProject();
 390  0
         stereo = project.getProfileConfiguration().findStereotypeForObject(
 391  
                 name, obj); 
 392  
 
 393  0
         if (stereo != null) {
 394  0
             return stereo;
 395  
         }
 396  
 
 397  0
         if (root != null && name.length() > 0) {
 398  0
             stereo =
 399  
                 Model.getExtensionMechanismsFactory().buildStereotype(
 400  
                     obj, name, root);
 401  
         }
 402  
 
 403  0
         return stereo;
 404  
     }
 405  
 
 406  
     /**
 407  
      * Search for a stereotype with the name given in a namespace and its
 408  
      * containing namespaces.
 409  
      * 
 410  
      * @param obj The model element to be suitable for.
 411  
      * @param namespace The namespace to start search at. If null, the namespace
 412  
      *                of the given model element will be used as the starting
 413  
      *                point.
 414  
      * @param name The name of the stereotype to search for.
 415  
      * @return An stereotype named name, or null if none is found.
 416  
      */
 417  
     private static Object findStereotype(
 418  
             final Object obj, final Object namespace, final String name) {
 419  0
         Object ns = namespace;
 420  0
         if (ns == null) {
 421  0
             ns = Model.getFacade().getNamespace(obj);
 422  0
             if (ns == null) {
 423  0
                 return null;
 424  
             }
 425  
         }
 426  
 
 427  
         
 428  0
         Collection ownedElements = 
 429  
             Model.getFacade().getOwnedElements(ns);
 430  0
         for (Object element : ownedElements) {
 431  0
             if (Model.getFacade().isAStereotype(element)
 432  
                     && name.equals(Model.getFacade().getName(element))) {
 433  0
                 return element;
 434  
             }
 435  
         }
 436  
         
 437  
         // If not found, try the parent namespace
 438  0
         ns = Model.getFacade().getNamespace(ns);
 439  0
         if (namespace != null) {
 440  0
             return findStereotype(obj, ns, name);
 441  
         }
 442  
 
 443  0
         return null;
 444  
     }
 445  
     
 446  
     /**
 447  
      * Search descending recursively for a stereotype with the name given
 448  
      * in name.  NOTE: You probably don't want to use this because it's 
 449  
      * searching the wrong direction!
 450  
      *
 451  
      * @param obj
 452  
      *            The model element to be suitable for.
 453  
      * @param root
 454  
      *            The model element to search from.
 455  
      * @param name
 456  
      *            The name of the stereotype to search for.
 457  
      * @return An stereotype named name, or null if none is found.
 458  
      */
 459  
     private static Object findStereotypeContained(
 460  
             Object obj, Object root, String name) {
 461  
         Object stereo;
 462  
 
 463  0
         if (root == null) {
 464  0
             return null;
 465  
         }
 466  
         
 467  0
         if (Model.getFacade().isAStereotype(root)
 468  
                 && name.equals(Model.getFacade().getName(root))) {
 469  0
             if (Model.getExtensionMechanismsHelper().isValidStereotype(obj,
 470  
                     root)) {
 471  0
                 return root;
 472  
             }
 473  
         }
 474  
 
 475  0
         if (!Model.getFacade().isANamespace(root)) {
 476  0
             return null;
 477  
         }
 478  
 
 479  0
         Collection ownedElements = Model.getFacade().getOwnedElements(root);
 480  
 
 481  
         // Loop through each element in the namespace, recursing.
 482  0
         for (Object ownedElement : ownedElements) {
 483  0
             stereo = findStereotypeContained(obj, ownedElement, name);
 484  0
             if (stereo != null) {
 485  0
                 return stereo;
 486  
             }
 487  
         }
 488  0
         return null;
 489  
     }
 490  
 
 491  
 }