Coverage Report - org.argouml.kernel.ProjectImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ProjectImpl
57%
247/430
35%
70/196
2.438
ProjectImpl$1
60%
3/5
N/A
2.438
ProjectImpl$2
60%
3/5
N/A
2.438
ProjectImpl$3
60%
3/5
N/A
2.438
ProjectImpl$NamePCL
33%
1/3
N/A
2.438
 
 1  
 /* $Id: ProjectImpl.java 18921 2010-12-15 18:16:53Z thn $
 2  
  *******************************************************************************
 3  
  * Copyright (c) 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  
  *    Tom Morris
 11  
  *    Bob Tarling
 12  
  *    Michiel van der Wulp
 13  
  *******************************************************************************
 14  
  *
 15  
  * Some portions of this file were previously release using the BSD License:
 16  
  */
 17  
 
 18  
 // $Id: ProjectImpl.java 18921 2010-12-15 18:16:53Z thn $
 19  
 // Copyright (c) 1996-2008 The Regents of the University of California. All
 20  
 // Rights Reserved. Permission to use, copy, modify, and distribute this
 21  
 // software and its documentation without fee, and without a written
 22  
 // agreement is hereby granted, provided that the above copyright notice
 23  
 // and this paragraph appear in all copies.  This software program and
 24  
 // documentation are copyrighted by The Regents of the University of
 25  
 // California. The software program and documentation are supplied "AS
 26  
 // IS", without any accompanying services from The Regents. The Regents
 27  
 // does not warrant that the operation of the program will be
 28  
 // uninterrupted or error-free. The end-user understands that the program
 29  
 // was developed for research purposes and is advised not to rely
 30  
 // exclusively on the program for any reason.  IN NO EVENT SHALL THE
 31  
 // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
 32  
 // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
 33  
 // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 34  
 // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 35  
 // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
 36  
 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 37  
 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 38  
 // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 39  
 // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
 40  
 // UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 41  
 
 42  
 package org.argouml.kernel;
 43  
 
 44  
 import java.beans.PropertyChangeEvent;
 45  
 import java.beans.PropertyChangeListener;
 46  
 import java.beans.PropertyVetoException;
 47  
 import java.beans.VetoableChangeSupport;
 48  
 import java.io.File;
 49  
 import java.net.URI;
 50  
 import java.util.ArrayList;
 51  
 import java.util.Collection;
 52  
 import java.util.Collections;
 53  
 import java.util.HashMap;
 54  
 import java.util.HashSet;
 55  
 import java.util.Iterator;
 56  
 import java.util.List;
 57  
 import java.util.Map;
 58  
 import java.util.Set;
 59  
 
 60  
 import org.apache.log4j.Logger;
 61  
 import org.argouml.application.api.Argo;
 62  
 import org.argouml.application.helpers.ApplicationVersion;
 63  
 import org.argouml.configuration.Configuration;
 64  
 import org.argouml.i18n.Translator;
 65  
 import org.argouml.model.InvalidElementException;
 66  
 import org.argouml.model.Model;
 67  
 import org.argouml.profile.Profile;
 68  
 import org.argouml.profile.ProfileFacade;
 69  
 import org.argouml.ui.targetmanager.TargetManager;
 70  
 import org.argouml.uml.CommentEdge;
 71  
 import org.argouml.uml.ProjectMemberModel;
 72  
 import org.argouml.uml.cognitive.ProjectMemberTodoList;
 73  
 import org.argouml.uml.diagram.ArgoDiagram;
 74  
 import org.argouml.uml.diagram.DiagramFactory;
 75  
 import org.argouml.uml.diagram.ProjectMemberDiagram;
 76  
 import org.tigris.gef.presentation.Fig;
 77  
 
 78  
 /**
 79  
  * The ProjectImpl is a data structure that represents the designer's
 80  
  * current project. It manages the list of diagrams and UML models.
 81  
  * <p>
 82  
  * NOTE: This was named Project until 0.25.4 when it was replaced by an
 83  
  * interface of the same name and renamed to ProjectImpl.
 84  
  */
 85  36
 public class ProjectImpl implements java.io.Serializable, Project {
 86  
 
 87  900
     private static final Logger LOG = Logger.getLogger(ProjectImpl.class);
 88  
 
 89  
     /**
 90  
      * Default name for a project.
 91  
      */
 92  900
     private static final String UNTITLED_FILE =
 93  
         Translator.localize("label.projectbrowser-title");
 94  
 
 95  
     /**
 96  
      * The project type
 97  
      */
 98  968
     private int projectType = UML_PROJECT;
 99  
 
 100  
     /**
 101  
      * The UID.
 102  
      */
 103  
     static final long serialVersionUID = 1399111233978692444L;
 104  
 
 105  
     /**
 106  
      * TODO: should just be the directory to write.
 107  
      */
 108  
     private URI uri;
 109  
 
 110  
     /* The preferences with project-scope: */
 111  
     private String authorname;
 112  
     private String authoremail;
 113  
     private String description;
 114  
     /* The ArgoUML version with which this project was last saved: */
 115  
     private String version;
 116  
 
 117  
     private ProjectSettings projectSettings;
 118  
 
 119  968
     private final List<String> searchpath = new ArrayList<String>();
 120  
 
 121  
     // TODO: break into 3 main member types
 122  
     // model, diagram and other
 123  968
     private final List<ProjectMember> members = new MemberList();
 124  
 
 125  
     private String historyFile;
 126  
 
 127  
     /**
 128  
      * The version number of the persistence format that last
 129  
      * saved this project.
 130  
      */
 131  
     private int persistenceVersion;
 132  
 
 133  
     /**
 134  
      * Instances of the UML model.
 135  
      */
 136  968
     private final List models = new ArrayList();
 137  
     
 138  
     private Object root;
 139  968
     private final Collection roots = new HashSet();
 140  
 
 141  
     /**
 142  
      * Instances of the UML diagrams.
 143  
      */
 144  968
     private final List<ArgoDiagram> diagrams = new ArrayList<ArgoDiagram>();
 145  
     
 146  
     private Object currentNamespace;
 147  
     private Map<String, Object> uuidRefs;
 148  
     private transient VetoableChangeSupport vetoSupport;
 149  
 
 150  
     private ProfileConfiguration profileConfiguration;
 151  
 
 152  
     /**
 153  
      * The active diagram, pointer to a diagram in the list with diagrams.
 154  
      */
 155  
     private ArgoDiagram activeDiagram;
 156  
     
 157  
     /** The name of the diagram to show by default after loading a project. */
 158  
     private String savedDiagramName;
 159  
 
 160  
     /**
 161  
      * Cache for the default model.
 162  
      */
 163  968
     private HashMap<String, Object> defaultModelTypeCache = 
 164  
         new HashMap<String, Object>();
 165  
 
 166  968
     private final Collection trashcan = new ArrayList();
 167  
 
 168  
     // TODO: Change this to use an UndoManager instance per project when
 169  
     // GEF has been enhanced.
 170  968
     private UndoManager undoManager = new DefaultUndoManager(this);
 171  
 
 172  968
     private boolean dirty = false;
 173  
     
 174  
     /**
 175  
      * Constructor.
 176  
      *
 177  
      * @param theProjectUri Uri to read the project from.
 178  
      */
 179  
     public ProjectImpl(int type, URI theProjectUri) {
 180  0
         this(UML_PROJECT);
 181  
         /* TODO: Why was this next line in the code so long? */
 182  
 //        uri = PersistenceManager.getInstance().fixUriExtension(theProjectUri);
 183  0
         uri = theProjectUri;
 184  0
     }
 185  
 
 186  
     /**
 187  
      * Constructor.
 188  
      */
 189  
     public ProjectImpl() {
 190  954
         this(UML_PROJECT);
 191  954
     }
 192  
 
 193  
     /**
 194  
      * Constructor.
 195  
      */
 196  968
     public ProjectImpl(int type) {
 197  968
         projectType = type;
 198  968
         setProfileConfiguration(new ProfileConfiguration(this));
 199  
 
 200  968
         projectSettings = new ProjectSettings(this);
 201  
 
 202  968
         Model.getModelManagementFactory().setRootModel(null);
 203  
 
 204  968
         authorname = Configuration.getString(Argo.KEY_USER_FULLNAME);
 205  968
         authoremail = Configuration.getString(Argo.KEY_USER_EMAIL);
 206  968
         description = "";
 207  
         // this should be moved to a ui action.
 208  968
         version = ApplicationVersion.getVersion();
 209  
 
 210  968
         historyFile = "";
 211  
 
 212  968
         LOG.info("making empty project with empty model");
 213  968
         addSearchPath("PROJECT_DIR");
 214  968
     }
 215  
 
 216  
 
 217  
     public String getName() {
 218  
         // TODO: maybe separate name
 219  6232
         if (uri == null) {
 220  6232
             return UNTITLED_FILE;
 221  
         }
 222  0
         return new File(uri).getName();
 223  
     }
 224  
 
 225  
     public int getProjectType() {
 226  968
         return projectType;
 227  
     }
 228  
     
 229  
     public void setProjectType(int projectType) {
 230  0
         this.projectType = projectType;
 231  0
     }
 232  
 
 233  
     public URI getUri() {
 234  8864
         return uri;
 235  
     }
 236  
 
 237  
 
 238  
     public URI getURI() {
 239  121
         return uri;
 240  
     }
 241  
 
 242  
     /**
 243  
      * @param theUri the URI for the project
 244  
      */
 245  
     public void setUri(URI theUri) {
 246  0
         if (LOG.isDebugEnabled()) {
 247  0
             LOG.debug("Setting project URI from \"" + uri
 248  
                       + "\" to \"" + theUri + "\".");
 249  
         }
 250  0
         uri = theUri;
 251  0
     }
 252  
 
 253  
     public void setFile(final File file) {
 254  0
         URI theProjectUri = file.toURI();
 255  
 
 256  0
         if (LOG.isDebugEnabled()) {
 257  0
             LOG.debug("Setting project file name from \""
 258  
                       + uri
 259  
                       + "\" to \""
 260  
                       + theProjectUri
 261  
                       + "\".");
 262  
         }
 263  
 
 264  0
         uri = theProjectUri;
 265  0
     }
 266  
 
 267  
 
 268  
     public List<String> getSearchPathList() {
 269  0
         return Collections.unmodifiableList(searchpath);
 270  
     }
 271  
 
 272  
 
 273  
     public void addSearchPath(final String searchPathElement) {
 274  968
         if (!searchpath.contains(searchPathElement)) {
 275  968
             searchpath.add(searchPathElement);
 276  
         }
 277  968
     }
 278  
 
 279  
 
 280  
     public List<ProjectMember> getMembers() {
 281  0
         LOG.info("Getting the members there are " + members.size());
 282  0
         return members;
 283  
     }
 284  
 
 285  
     /**
 286  
      * @param d the diagram
 287  
      */
 288  
     private void addDiagramMember(ArgoDiagram d) {
 289  
         // Check for duplicate name and rename if necessary
 290  2116
         int serial = getDiagramCount();
 291  2194
         while (!isValidDiagramName(d.getName())) {
 292  
             try {
 293  78
                 d.setName(d.getName() + " " + serial);
 294  0
             } catch (PropertyVetoException e) {
 295  0
                 serial++;            
 296  78
             }
 297  
         }
 298  2116
         ProjectMember pm = new ProjectMemberDiagram(d, this);
 299  2116
         addDiagram(d);
 300  
         // if diagram added successfully, add the member too
 301  2116
         members.add(pm);
 302  2116
     }
 303  
 
 304  
     /**
 305  
      * @param pm the member to be added
 306  
      */
 307  
     private void addTodoMember(ProjectMemberTodoList pm) {
 308  
         // Adding a todo member removes any existing one.
 309  1922
         members.add(pm);
 310  1922
         LOG.info("Added todo member, there are now " + members.size());
 311  1922
     }
 312  
 
 313  
 
 314  
     public void addMember(Object m) {
 315  
 
 316  5006
         if (m == null) {
 317  0
             throw new IllegalArgumentException(
 318  
                     "A model member must be supplied");
 319  5006
         } else if (m instanceof ArgoDiagram) {
 320  2116
             LOG.info("Adding diagram member");
 321  2116
             addDiagramMember((ArgoDiagram) m);
 322  2890
         } else if (m instanceof ProjectMemberTodoList) {
 323  1922
             LOG.info("Adding todo member");
 324  1922
             addTodoMember((ProjectMemberTodoList) m);
 325  968
         } else if (Model.getFacade().isAModel(m)) {
 326  968
             LOG.info("Adding model member");
 327  968
             addModelMember(m);
 328  0
         } else if (Model.getFacade().isAProfile(m)) {
 329  0
             LOG.info("Adding profile model member");
 330  0
             addModelMember(m);
 331  
         } else {
 332  0
             throw new IllegalArgumentException(
 333  
                     "The member must be a UML model todo member or diagram."
 334  
                     + "It is " + m.getClass().getName());
 335  
         }
 336  5006
         LOG.info("There are now " + members.size() + " members");
 337  5006
     }
 338  
 
 339  
     /**
 340  
      * @param m the model
 341  
      */
 342  
     private void addModelMember(final Object m) {
 343  
 
 344  968
         boolean memberFound = false;
 345  968
         Object currentMember =
 346  
             members.get(0);
 347  968
         if (currentMember instanceof ProjectMemberModel) {
 348  0
             Object currentModel =
 349  
                 ((ProjectMemberModel) currentMember).getModel();
 350  0
             if (currentModel == m) {
 351  0
                 memberFound = true;
 352  
             }
 353  
         }
 354  
 
 355  968
         if (!memberFound) {
 356  968
             if (!models.contains(m)) {
 357  0
                 addModel(m);
 358  
             }
 359  
             // got past the veto, add the member
 360  968
             ProjectMember pm = new ProjectMemberModel(m, this);
 361  968
             LOG.info("Adding model member to start of member list");
 362  968
             members.add(pm);
 363  968
         } else {
 364  0
             LOG.info("Attempted to load 2 models");
 365  0
             throw new IllegalArgumentException(
 366  
                     "Attempted to load 2 models");
 367  
         }
 368  968
     }
 369  
 
 370  
 
 371  
     public void addModel(final Object model) {
 372  
 
 373  968
         if (!Model.getFacade().isAModel(model)
 374  
              && !Model.getFacade().isAProfile(model)) {
 375  0
             throw new IllegalArgumentException();
 376  
         }
 377  968
         if (!models.contains(model)) {
 378  968
             setRoot(model);
 379  
         }        
 380  968
     }
 381  
 
 382  
     private void addModelInternal(final Object model) {
 383  1936
         models.add(model);
 384  1936
         roots.add(model);
 385  1936
         setCurrentNamespace(model);
 386  1936
         setSaveEnabled(true);
 387  1936
         if (models.size() > 1 || roots.size() > 1) {
 388  0
             LOG.debug("Multiple roots/models");
 389  
         }
 390  1936
     }
 391  
 
 392  
     /**
 393  
      * Removes a project member diagram completely from the project.
 394  
      * @param d the ArgoDiagram
 395  
      */
 396  
     protected void removeProjectMemberDiagram(ArgoDiagram d) {
 397  38
         if (activeDiagram == d) {
 398  38
             LOG.debug("Deleting active diagram " + d);
 399  38
             ArgoDiagram defaultDiagram = null;
 400  38
             if (diagrams.size() == 1) {
 401  
                 // We're deleting the last diagram so lets create a new one
 402  
                 // TODO: Once we go MDI we won't need this.
 403  1
                 LOG.debug("Deleting last diagram - creating new default diag");
 404  1
                 Object projectRoot = getRoot();
 405  1
                 if (!Model.getUmlFactory().isRemoved(projectRoot)) {
 406  1
                     defaultDiagram = DiagramFactory.getInstance()
 407  
                             .createDefaultDiagram(projectRoot);
 408  1
                     addMember(defaultDiagram);
 409  
                 }
 410  1
             } else {
 411  
                 // Make the topmost diagram (that is not the one being deleted)
 412  
                 // current.
 413  37
                 defaultDiagram = diagrams.get(0);
 414  37
                 LOG.debug("Candidate default diagram is " + defaultDiagram);
 415  37
                 if (defaultDiagram == d) {
 416  34
                     defaultDiagram = diagrams.get(1);
 417  34
                     LOG.debug("Switching default diagram to " + defaultDiagram);
 418  
                 }
 419  
             }
 420  38
             activeDiagram = defaultDiagram;
 421  38
             TargetManager.getInstance().setTarget(activeDiagram);
 422  38
             LOG.debug("New active diagram is " + defaultDiagram);
 423  
         }
 424  
 
 425  38
         removeDiagram(d);
 426  38
         members.remove(d);
 427  38
         d.remove();
 428  38
         setSaveEnabled(true);
 429  38
     }
 430  
     
 431  
     /**
 432  
      * Enables the save action if this project is the current project
 433  
      * @param enable true to enable
 434  
      */
 435  
     private void setSaveEnabled(boolean enable) {
 436  4090
         ProjectManager pm = ProjectManager.getManager();
 437  4090
         if (pm.getCurrentProject() == this) {
 438  232
             pm.setSaveEnabled(enable);
 439  
         }
 440  4090
     }
 441  
 
 442  
 
 443  
     public String getAuthorname() {
 444  106
         return authorname;
 445  
     }
 446  
 
 447  
 
 448  
     public void setAuthorname(final String s) {
 449  12
         final String oldAuthorName = authorname;
 450  12
         AbstractCommand command = new AbstractCommand() {
 451  
             public Object execute() {
 452  12
                 authorname = s;
 453  12
                 return null;
 454  
             }
 455  
 
 456  
             public void undo() {
 457  0
                 authorname = oldAuthorName;
 458  0
             }
 459  
         };
 460  12
         undoManager.execute(command);
 461  12
     }
 462  
 
 463  
 
 464  
     public String getAuthoremail() {
 465  106
         return authoremail;
 466  
     }
 467  
 
 468  
 
 469  
     public void setAuthoremail(final String s) {
 470  12
         final String oldAuthorEmail = authoremail;
 471  12
         AbstractCommand command = new AbstractCommand() {
 472  
             public Object execute() {
 473  12
                 authoremail = s;
 474  12
                 return null;
 475  
             }
 476  
 
 477  
             public void undo() {
 478  0
                 authoremail = oldAuthorEmail;
 479  0
             }
 480  
         };
 481  12
         undoManager.execute(command);
 482  12
     }
 483  
 
 484  
 
 485  
     public String getVersion() {
 486  106
         return version;
 487  
     }
 488  
 
 489  
 
 490  
     public void setVersion(String s) {
 491  0
         version = s;
 492  0
     }
 493  
 
 494  
 
 495  
     public String getDescription() {
 496  106
         return description;
 497  
     }
 498  
 
 499  
 
 500  
     public void setDescription(final String s) {
 501  12
         final String oldDescription = description;
 502  12
         AbstractCommand command = new AbstractCommand() {
 503  
             public Object execute() {
 504  12
                 description = s;
 505  12
                 return null;
 506  
             }
 507  
 
 508  
             public void undo() {
 509  0
                 description = oldDescription;
 510  0
             }
 511  
         };
 512  12
         undoManager.execute(command);
 513  12
     }
 514  
 
 515  
 
 516  
     public String getHistoryFile() {
 517  0
         return historyFile;
 518  
     }
 519  
 
 520  
 
 521  
     public void setHistoryFile(final String s) {
 522  0
         historyFile = s;
 523  0
     }
 524  
 
 525  
 
 526  
     public List getUserDefinedModelList() {
 527  41445
         return models;
 528  
     }
 529  
 
 530  
 
 531  
     public Collection getModels() {
 532  0
         Set result = new HashSet();
 533  0
         result.addAll(models);
 534  0
         for (Profile profile : getProfileConfiguration().getProfiles()) {
 535  
             try {
 536  0
                 result.addAll(profile.getProfilePackages());
 537  0
             } catch (org.argouml.profile.ProfileException e) {
 538  0
                 LOG.error("Exception when fetching models from profile "
 539  
                         + profile.getDisplayName(), e);
 540  0
             }
 541  
         }
 542  0
         return Collections.unmodifiableCollection(result);
 543  
     }
 544  
 
 545  
     /**
 546  
      * Return the model.<p>
 547  
      *
 548  
      * If there isn't exactly one model, <code>null</code> is returned.
 549  
      *
 550  
      * @return the model.
 551  
      * @deprecated for 0.25.4 by tfmorris.  Use 
 552  
      * {@link #getUserDefinedModelList()} or {@link #getModels()}.
 553  
      * @see org.argouml.kernel.Project#getModel()
 554  
      */
 555  
     @SuppressWarnings("deprecation")
 556  
     @Deprecated
 557  
     public Object getModel() {
 558  0
         if (models.size() != 1) {
 559  0
             return null;
 560  
         }
 561  0
         return models.iterator().next();
 562  
     }
 563  
 
 564  
 
 565  
     public Object findType(String s) {
 566  0
         return findType(s, true);
 567  
     }
 568  
 
 569  
 
 570  
     public Object getDefaultAttributeType() {
 571  0
         if (profileConfiguration.getDefaultTypeStrategy() != null) {
 572  0
             return profileConfiguration.getDefaultTypeStrategy()
 573  
                     .getDefaultAttributeType();
 574  
         }
 575  0
         return null;
 576  
     }
 577  
 
 578  
 
 579  
     public Object getDefaultParameterType() {
 580  0
         if (profileConfiguration.getDefaultTypeStrategy() != null) {
 581  0
             return profileConfiguration.getDefaultTypeStrategy()
 582  
                     .getDefaultParameterType();
 583  
         }
 584  0
         return null;
 585  
     }
 586  
     
 587  
 
 588  
     public Object getDefaultReturnType() {
 589  0
         if (profileConfiguration.getDefaultTypeStrategy() != null) {
 590  0
             return profileConfiguration.getDefaultTypeStrategy()
 591  
                     .getDefaultReturnType();
 592  
         }
 593  0
         return null;
 594  
     }
 595  
 
 596  
 
 597  
     public Object findType(String s, boolean defineNew) {
 598  0
         if (s != null) {
 599  0
             s = s.trim();
 600  
         }
 601  0
         if (s == null || s.length() == 0) {
 602  0
             return null;
 603  
         }
 604  0
         Object cls = null;
 605  0
         for (Object model : models) {
 606  0
             cls = findTypeInModel(s, model);
 607  0
             if (cls != null) {
 608  0
                 return cls;
 609  
             }
 610  
         }
 611  0
         cls = findTypeInDefaultModel(s);
 612  
 
 613  0
         if (cls == null && defineNew) {
 614  0
             LOG.debug("new Type defined!");
 615  0
             cls =
 616  
                 Model.getCoreFactory().buildClass(getCurrentNamespace());
 617  0
             Model.getCoreHelper().setName(cls, s);
 618  
         }
 619  0
         return cls;
 620  
     }
 621  
 
 622  
 
 623  
     public Collection<Fig> findFigsForMember(Object member) {
 624  1201
         Collection<Fig> figs = new ArrayList<Fig>();
 625  1201
         for (ArgoDiagram diagram : diagrams) {
 626  2598
             Fig fig = diagram.getContainingFig(member);
 627  2598
             if (fig != null) {
 628  0
                 figs.add(fig);
 629  
             }
 630  2598
         }
 631  1201
         return figs;
 632  
     }
 633  
 
 634  
 
 635  
     public Collection findAllPresentationsFor(Object obj) {
 636  126
         Collection<Fig> figs = new ArrayList<Fig>();
 637  126
         for (ArgoDiagram diagram : diagrams) {
 638  217
             Fig aFig = diagram.presentationFor(obj);
 639  217
             if (aFig != null) {
 640  0
                 figs.add(aFig);
 641  
             }
 642  217
         }
 643  126
         return figs;
 644  
     }
 645  
 
 646  
     public Object findTypeInModel(String typeName, Object namespace) {
 647  0
         if (typeName == null) {
 648  0
             throw new IllegalArgumentException("typeName must be non-null");
 649  
         }
 650  0
         if (!Model.getFacade().isANamespace(namespace)) {
 651  0
             throw new IllegalArgumentException(
 652  
                     "Looking for the classifier " + typeName
 653  
                     + " in a non-namespace object of " + namespace
 654  
                     + ". A namespace was expected.");
 655  
             }
 656  
 
 657  0
         Collection allClassifiers =
 658  
             Model.getModelManagementHelper()
 659  
                 .getAllModelElementsOfKind(namespace,
 660  
                         Model.getMetaTypes().getClassifier());
 661  
 
 662  0
         for (Object classifier : allClassifiers) {
 663  0
             if (typeName.equals(Model.getFacade().getName(classifier))) {
 664  0
                 return classifier;
 665  
             }
 666  
         }
 667  
 
 668  0
         return null;
 669  
     }
 670  
 
 671  
 
 672  
     @SuppressWarnings("deprecation")
 673  
     @Deprecated
 674  
     public void setCurrentNamespace(final Object m) {
 675  
 
 676  4231
         if (m != null && !Model.getFacade().isANamespace(m)) {
 677  0
             throw new IllegalArgumentException();
 678  
             }
 679  
 
 680  4231
         currentNamespace = m;
 681  4231
     }
 682  
 
 683  
 
 684  
     @SuppressWarnings("deprecation")
 685  
     @Deprecated
 686  
     public Object getCurrentNamespace() {
 687  0
         return currentNamespace;
 688  
     }
 689  
 
 690  
 
 691  
     public List<ArgoDiagram> getDiagramList() {
 692  40712
         return Collections.unmodifiableList(diagrams);
 693  
     }
 694  
 
 695  
 
 696  
     public int getDiagramCount() {
 697  2116
         return diagrams.size();
 698  
     }
 699  
 
 700  
 
 701  
     public ArgoDiagram getDiagram(String name) {
 702  0
         for (ArgoDiagram ad : diagrams) {
 703  0
             if (ad.getName() != null && ad.getName().equals(name)) {
 704  0
                 return ad;
 705  
             }
 706  0
             if (ad.getItemUID() != null
 707  
                     && ad.getItemUID().toString().equals(name)) {
 708  0
                 return ad;
 709  
             }
 710  
         }
 711  0
         return null;
 712  
     }
 713  
 
 714  
 
 715  
     public void addDiagram(final ArgoDiagram d) {
 716  
         // send indeterminate new value instead of making copy of vector
 717  2116
         d.setProject(this);
 718  2116
         diagrams.add(d);
 719  
 
 720  2116
         d.addPropertyChangeListener("name", new NamePCL());
 721  2116
         setSaveEnabled(true);
 722  2116
     }
 723  
 
 724  
     /**
 725  
      * Listener to events from the Diagram class. <p>
 726  
      *
 727  
      * Purpose: changing the name of a diagram shall set the need save flag.
 728  
      *
 729  
      * @author Michiel
 730  
      */
 731  4232
     private class NamePCL implements PropertyChangeListener {
 732  
         public void propertyChange(PropertyChangeEvent evt) {
 733  0
             setSaveEnabled(true);
 734  0
         }
 735  
     }
 736  
 
 737  
     /**
 738  
      * Removes a diagram from the list with diagrams.
 739  
      *
 740  
      * Removes (hopefully) the event listeners for this diagram.  Does
 741  
      * not remove the diagram from the project members. This should
 742  
      * not be called directly. Use moveToTrash if you want to remove a
 743  
      * diagram.
 744  
      *
 745  
      * @param d the ArgoDiagram
 746  
      */
 747  
     protected void removeDiagram(ArgoDiagram d) {
 748  38
         diagrams.remove(d);
 749  
         /* Remove the dependent
 750  
          * modelelements, such as the statemachine
 751  
          * for a statechartdiagram:
 752  
          */
 753  38
         Object o = d.getDependentElement();
 754  38
         if (o != null) {
 755  1
             moveToTrash(o);
 756  
         }
 757  38
     }
 758  
 
 759  
     public int getPresentationCountFor(Object me) {
 760  
 
 761  0
         if (!Model.getFacade().isAUMLElement(me)) {
 762  0
             throw new IllegalArgumentException();
 763  
             }
 764  
 
 765  0
         int presentations = 0;
 766  0
         for (ArgoDiagram d : diagrams) {
 767  0
             presentations += d.getLayer().presentationCountFor(me);
 768  
         }
 769  0
         return presentations;
 770  
     }
 771  
 
 772  
 
 773  
     public Object getInitialTarget() {
 774  1868
         if (savedDiagramName != null) {
 775  
             /* Hence, a diagram name was saved in the project 
 776  
              * that we are loading. So, we use this name 
 777  
              * to retrieve any matching diagram. */
 778  0
             return getDiagram(savedDiagramName);
 779  
         }
 780  1868
         if (diagrams.size() > 0) {
 781  
             /* Use the first diagram. */
 782  1868
             return diagrams.get(0);
 783  
         }
 784  0
         if (models.size() > 0) {
 785  
             /* If there was no diagram at all, 
 786  
              * then use the (first) UML model. */
 787  0
             return models.iterator().next();
 788  
         }
 789  0
         return null;
 790  
     }
 791  
 
 792  
     public void preSave() {
 793  0
         for (ArgoDiagram diagram : diagrams) {
 794  0
             diagram.preSave();
 795  
         }
 796  0
     }
 797  
 
 798  
     public void postSave() {
 799  0
         for (ArgoDiagram diagram : diagrams) {
 800  0
             diagram.postSave();
 801  
         }
 802  0
         setSaveEnabled(true);
 803  0
     }
 804  
 
 805  
     public void postLoad() {
 806  0
         long startTime = System.currentTimeMillis();
 807  0
         for (ArgoDiagram diagram : diagrams) {
 808  0
             diagram.postLoad();
 809  
         }
 810  0
         long endTime = System.currentTimeMillis();
 811  0
         LOG.debug("Diagram post load took " + (endTime - startTime) + " msec.");
 812  
         
 813  
         // issue 1725: the root is not set, which leads to problems
 814  
         // with displaying prop panels
 815  0
         Object model = getModel();
 816  
 
 817  0
         LOG.info("Setting root model to " + model);
 818  
 
 819  0
         setRoot(model);
 820  
 
 821  0
         setSaveEnabled(true);
 822  
         // we don't need this HashMap anymore so free up the memory
 823  0
         uuidRefs = null;
 824  0
     }
 825  
 
 826  
     ////////////////////////////////////////////////////////////////
 827  
     // trash related methods
 828  
 
 829  
     /**
 830  
      * Empty the trash can and permanently delete all objects that it contains.
 831  
      */
 832  
     private void emptyTrashCan() {
 833  68
         trashcan.clear();
 834  68
     }
 835  
 
 836  
     public void moveToTrash(Object obj) {
 837  40
         if (obj instanceof Collection) {
 838  0
             Iterator i = ((Collection) obj).iterator();
 839  0
             while (i.hasNext()) {
 840  0
                 Object trash = i.next();
 841  0
                 if (!trashcan.contains(trash)) {
 842  0
                     trashInternal(trash);
 843  
                 }
 844  0
             }
 845  0
         } else {
 846  40
             if (!trashcan.contains(obj)) {
 847  39
                 trashInternal(obj);
 848  
             }
 849  
         }
 850  40
     }
 851  
 
 852  
     /**
 853  
      * Removes some object from the project.
 854  
      *
 855  
      * @param obj the object to be thrown away
 856  
      */
 857  
     protected void trashInternal(Object obj) {
 858  
         // TODO: This should only be checking for the top level package
 859  
         // (if anything at all)
 860  39
         if (Model.getFacade().isAModel(obj)) {
 861  0
             return; //Can not delete the model
 862  
         }
 863  39
         if (Model.getFacade().isAProfile(obj)) {
 864  0
             return; //Can not delete the profile
 865  
         }
 866  
 
 867  39
         if (obj != null) {
 868  39
             trashcan.add(obj);
 869  
         }
 870  39
         if (Model.getFacade().isAUMLElement(obj)) {
 871  
 
 872  1
             Model.getUmlFactory().delete(obj);
 873  
 
 874  
             // TODO: Presumably this is only relevant if
 875  
             // obj is actually a Model or Profile.
 876  
             // An added test of isAModel(obj) or isAProfile(obj) would clarify
 877  
             // what is going on here.
 878  1
             if (models.contains(obj)) {
 879  0
                 models.remove(obj);
 880  
             }
 881  38
         } else if (obj instanceof ArgoDiagram) {
 882  38
             removeProjectMemberDiagram((ArgoDiagram) obj);
 883  
             // Fire an event some anyone who cares about diagrams being
 884  
             // removed can listen for it
 885  38
             ProjectManager.getManager()
 886  
                     .firePropertyChanged("remove", obj, null);
 887  0
         } else if (obj instanceof Fig) {
 888  0
             ((Fig) obj).deleteFromModel();
 889  
             // If we delete a FigEdge
 890  
             // or FigNode we actually call this method with the owner not
 891  
             // the Fig itself. However, this method 
 892  
             // is called by ActionDeleteModelElements
 893  
             // for primitive Figs (without owner).
 894  0
             LOG.info("Request to delete a Fig " + obj.getClass().getName());
 895  0
         } else if (obj instanceof CommentEdge) {
 896  
             // TODO: Why is this a special case? - tfm
 897  0
             CommentEdge ce = (CommentEdge) obj;
 898  0
             LOG.info("Removing the link from " + ce.getAnnotatedElement()
 899  
                     + " to " + ce.getComment());
 900  0
             ce.delete();
 901  
         }
 902  39
     }
 903  
 
 904  
 
 905  
     @SuppressWarnings("deprecation")
 906  
     @Deprecated
 907  
     public boolean isInTrash(Object obj) {
 908  0
         return trashcan.contains(obj);
 909  
     }
 910  
 
 911  
 
 912  
 
 913  
     public Object findTypeInDefaultModel(String name) {
 914  570
         if (defaultModelTypeCache.containsKey(name)) {
 915  514
             return defaultModelTypeCache.get(name);
 916  
         }
 917  
         
 918  56
         Object result = profileConfiguration.findType(name);
 919  
         
 920  56
         defaultModelTypeCache.put(name, result);
 921  56
         return result;
 922  
     }
 923  
 
 924  
 
 925  
     @SuppressWarnings("deprecation")
 926  
     @Deprecated
 927  
     public final Object getRoot() {
 928  223
         return root;
 929  
     }
 930  
 
 931  
 
 932  
     @SuppressWarnings("deprecation")
 933  
     @Deprecated
 934  
     public void setRoot(final Object theRoot) {
 935  
 
 936  1936
         if (theRoot == null) {
 937  0
             throw new IllegalArgumentException(
 938  
                     "A root model element is required");
 939  
         }
 940  1936
         if (!Model.getFacade().isAModel(theRoot)
 941  
                 && !Model.getFacade().isAProfile(theRoot)) {
 942  0
             throw new IllegalArgumentException(
 943  
                     "The root model element must be a model - got "
 944  
                     + theRoot.getClass().getName());
 945  
         }
 946  
 
 947  1936
         Object treeRoot = Model.getModelManagementFactory().getRootModel();
 948  1936
         if (treeRoot != null) {
 949  968
             models.remove(treeRoot);
 950  
         }
 951  1936
         root = theRoot;
 952  
         // TODO: We don't really want to do the following, but I'm not sure
 953  
         // what depends on it - tfm - 20070725
 954  1936
         Model.getModelManagementFactory().setRootModel(theRoot);
 955  
         // TODO: End up with multiple models here
 956  1936
         addModelInternal(theRoot);
 957  1936
         roots.clear();
 958  1936
         roots.add(theRoot);
 959  1936
     }
 960  
 
 961  
 
 962  
     public final Collection getRoots() {
 963  6117
         return Collections.unmodifiableCollection(roots);
 964  
     }
 965  
 
 966  
 
 967  
     public void setRoots(final Collection elements) {
 968  968
         boolean modelFound = false;
 969  968
         for (Object element : elements) {
 970  968
             if (!Model.getFacade().isAPackage(element)) {
 971  0
                 LOG.warn("Top level element other than package found - " 
 972  
                         + Model.getFacade().getName(element));
 973  
             }
 974  968
             if (Model.getFacade().isAModel(element)
 975  
                  || Model.getFacade().isAProfile(element) ) {
 976  968
                 addModel(element);
 977  968
                 if (!modelFound) {
 978  968
                     setRoot(element);
 979  968
                     modelFound = true;
 980  
                 }
 981  
             }
 982  
         }
 983  968
         roots.clear();
 984  968
         roots.addAll(elements);
 985  968
     }
 986  
 
 987  
     public void updateRoots() {
 988  0
         if (Model.getFacade().getUmlVersion().charAt(0) == '1') {
 989  
             // not needed in UML 1.x
 990  0
             return;
 991  
         }
 992  0
         roots.clear();
 993  0
         for (Object m : models) {
 994  0
             for (Object e : Model.getModelManagementHelper().getRootElements(m)) {
 995  0
                 if (!roots.contains(e)) {
 996  0
                     roots.add(e);
 997  0
                     checkProfileFor(e, m);
 998  
                 }
 999  
             }
 1000  
         }
 1001  0
     }
 1002  
 
 1003  
     public boolean isValidDiagramName(String name) {
 1004  2194
         boolean rv = true;
 1005  2194
         for (ArgoDiagram diagram : diagrams) {
 1006  1453
             if (diagram.getName().equals(name)) {
 1007  78
                 rv = false;
 1008  78
                 break;
 1009  
             }
 1010  
         }
 1011  2194
         return rv;
 1012  
     }
 1013  
 
 1014  
 
 1015  
     public Map<String, Object> getUUIDRefs() {
 1016  0
         return uuidRefs;
 1017  
     }
 1018  
 
 1019  
     
 1020  
     public void setSearchPath(final List<String> theSearchpath) {
 1021  0
         searchpath.clear();
 1022  0
         searchpath.addAll(theSearchpath);
 1023  0
     }
 1024  
 
 1025  
     public void setUUIDRefs(Map<String, Object> uUIDRefs) {
 1026  0
         uuidRefs = uUIDRefs;
 1027  0
     }
 1028  
 
 1029  
     @SuppressWarnings("deprecation")
 1030  
     @Deprecated
 1031  
     public ArgoDiagram getActiveDiagram() {
 1032  1868
         return activeDiagram;
 1033  
     }
 1034  
 
 1035  
 
 1036  
 
 1037  
     @SuppressWarnings("deprecation")
 1038  
     @Deprecated
 1039  
     public void setActiveDiagram(final ArgoDiagram theDiagram) {
 1040  2169
         activeDiagram = theDiagram;
 1041  2169
     }
 1042  
     
 1043  
     public void setSavedDiagramName(String diagramName) {
 1044  0
         savedDiagramName = diagramName;
 1045  0
     }
 1046  
 
 1047  
     public void remove() {
 1048  68
         for (ArgoDiagram diagram : diagrams) {
 1049  136
             diagram.remove();
 1050  
         }
 1051  
 
 1052  68
         members.clear();
 1053  68
         if (!roots.isEmpty()) {
 1054  
             try {
 1055  68
                 Model.getUmlFactory().deleteExtent(roots.iterator().next());
 1056  0
             } catch (InvalidElementException e) {
 1057  0
                 LOG.warn("Extent deleted a second time");
 1058  68
             }
 1059  68
             roots.clear();
 1060  
         }
 1061  68
         models.clear();
 1062  68
         diagrams.clear();
 1063  68
         searchpath.clear();
 1064  
 
 1065  68
         if (uuidRefs != null) {
 1066  0
             uuidRefs.clear();
 1067  
         }
 1068  
 
 1069  68
         if (defaultModelTypeCache != null) {
 1070  68
             defaultModelTypeCache.clear();
 1071  
         }
 1072  
 
 1073  68
         uuidRefs = null;
 1074  68
         defaultModelTypeCache = null;
 1075  
 
 1076  68
         uri = null;
 1077  68
         authorname = null;
 1078  68
         authoremail = null;
 1079  68
         description = null;
 1080  68
         version = null;
 1081  68
         historyFile = null;
 1082  68
         currentNamespace = null;
 1083  68
         vetoSupport = null;
 1084  68
         activeDiagram = null;
 1085  68
         savedDiagramName = null;
 1086  
 
 1087  68
         emptyTrashCan();
 1088  68
     }
 1089  
 
 1090  
 
 1091  
     public int getPersistenceVersion() {
 1092  0
         return persistenceVersion;
 1093  
     }
 1094  
 
 1095  
 
 1096  
     public void setPersistenceVersion(int pv) {
 1097  0
         persistenceVersion = pv;
 1098  0
     }
 1099  
 
 1100  
 
 1101  
     public String repair() {
 1102  0
         StringBuilder report = new StringBuilder();
 1103  0
         Iterator it = members.iterator();
 1104  0
         while (it.hasNext()) {
 1105  0
             ProjectMember member = (ProjectMember) it.next();
 1106  0
             report.append(member.repair());
 1107  0
         }
 1108  0
         return report.toString();
 1109  
     }
 1110  
 
 1111  
 
 1112  
     public ProjectSettings getProjectSettings() {
 1113  2853
         return projectSettings;
 1114  
     }
 1115  
     public UndoManager getUndoManager() {
 1116  3935
         return undoManager;
 1117  
     }
 1118  
         
 1119  
     public ProfileConfiguration getProfileConfiguration() {
 1120  5298
         return profileConfiguration;
 1121  
     }
 1122  
 
 1123  
     public void setProfileConfiguration(ProfileConfiguration pc) {
 1124  980
         if (this.profileConfiguration != pc) {
 1125  968
             if (this.profileConfiguration != null) {
 1126  0
                 this.members.remove(this.profileConfiguration);
 1127  
             }
 1128  
 
 1129  968
             this.profileConfiguration = pc;
 1130  
 
 1131  
             // there's just one ProfileConfiguration in a project
 1132  
             // and there's no other way to add another one
 1133  968
             members.add(pc);
 1134  
         }
 1135  
         
 1136  980
         ProfileFacade.applyConfiguration(pc);
 1137  980
     }
 1138  
 
 1139  
     public boolean isDirty() {
 1140  
         // TODO: Placeholder implementation until support for tracking on
 1141  
         // a per-project basis is implemented
 1142  
 //        return dirty;
 1143  0
         return ProjectManager.getManager().isSaveActionEnabled();
 1144  
     }
 1145  
     
 1146  
     public void setDirty(boolean isDirty) {
 1147  
         // TODO: Placeholder implementation until support for tracking on
 1148  
         // a per-project basis is implemented
 1149  2127
         dirty = isDirty;
 1150  2127
         ProjectManager.getManager().setSaveEnabled(isDirty);
 1151  2127
     }
 1152  
 
 1153  
     private void checkProfileFor(Object o, Object m) {
 1154  0
         Profile profile = null;
 1155  0
         if (Model.getFacade().isAAppliedProfileElement(o)) {
 1156  0
             Object pkg = Model.getFacade().getNamespace(o);
 1157  0
             if (pkg != null) {
 1158  0
                 String name = Model.getFacade().getName(pkg);
 1159  0
                 profile = ProfileFacade.getManager()
 1160  
                         .lookForRegisteredProfile(name);
 1161  
             }
 1162  
         }
 1163  0
         if (profile != null) {
 1164  0
             getProfileConfiguration().addProfile(profile, m);
 1165  
         }
 1166  0
     }
 1167  
 }