View Javadoc

1   /*
2    *  Copyright (C) 2003-2005 SINTEF
3    *  Author:  Fredrik Vraalsen (fredrik dot vraalsen at sintef dot no)
4    *  Webpage: http://coras.sourceforge.net/
5    *
6    *  This program is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public License
8    *  as published by the Free Software Foundation; either version 2.1
9    *  of the License, or (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this program; if not, write to the Free
18   *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   *  02111-1307 USA
20   */
21  package coras.client;
22  
23  import java.awt.Component;
24  import java.awt.Cursor;
25  import java.awt.event.ActionEvent;
26  import java.awt.event.ActionListener;
27  import java.awt.event.KeyEvent;
28  import java.awt.event.MouseAdapter;
29  import java.io.File;
30  import java.io.FileInputStream;
31  import java.io.FileOutputStream;
32  import java.net.URL;
33  import java.text.SimpleDateFormat;
34  import java.util.ArrayList;
35  import java.util.Collection;
36  import java.util.Collections;
37  import java.util.HashMap;
38  import java.util.Hashtable;
39  import java.util.Iterator;
40  import java.util.Map;
41  import java.util.Observable;
42  import java.util.Observer;
43  import java.util.Properties;
44  
45  import javax.security.auth.login.LoginContext;
46  import javax.security.auth.login.LoginException;
47  import javax.swing.AbstractAction;
48  import javax.swing.JInternalFrame;
49  import javax.swing.JMenu;
50  import javax.swing.JMenuBar;
51  import javax.swing.JMenuItem;
52  import javax.swing.JOptionPane;
53  import javax.swing.JPopupMenu;
54  import javax.swing.JTree;
55  import javax.swing.SwingUtilities;
56  import javax.swing.event.InternalFrameAdapter;
57  import javax.swing.event.TreeSelectionEvent;
58  import javax.swing.event.TreeSelectionListener;
59  import javax.swing.tree.DefaultMutableTreeNode;
60  import javax.swing.tree.DefaultTreeModel;
61  import javax.swing.tree.MutableTreeNode;
62  import javax.swing.tree.TreePath;
63  
64  import no.sintef.assetrepository.Asset;
65  import no.sintef.file.IOUtils;
66  import no.sintef.lock.AlreadyLockedException;
67  import no.sintef.lock.LockException;
68  import no.sintef.lock.LockedByOtherUserException;
69  import coras.client.ui.CorasFrame;
70  import coras.client.ui.CorasTreeCellRenderer;
71  import coras.client.ui.ElementFrame;
72  import coras.client.ui.LoginDialog;
73  import coras.client.ui.NewPackageDialog;
74  import coras.client.ui.OpenPackageDialog;
75  import coras.client.ui.OpenProjectDialog;
76  import coras.client.ui.PackageFrame;
77  import coras.client.ui.PackagePanel;
78  import coras.client.ui.ProgressDialog;
79  import coras.client.ui.SaveVersionDialog;
80  import coras.client.ui.StartupWizard;
81  import coras.common.CorasAsset;
82  import coras.common.CorasElement;
83  import coras.common.CorasPackage;
84  import coras.repository.interfaces.CorasServices;
85  import coras.repository.interfaces.CorasServicesUtil;
86  import coras.representations.DiagramRepresentation;
87  import coras.representations.DocumentRepresentation;
88  import coras.representations.FaultTreeModel;
89  import coras.representations.RepresentationTypeEnum;
90  import coras.representations.UMLModelRepresentation;
91  import coras.reuse.CategoryEnum;
92  import coras.reuse.Experience;
93  import coras.reuse.ExperiencePackage;
94  import coras.riskanalysis.RiskAnalysisProject;
95  import coras.riskanalysis.RiskAnalysisResult;
96  import coras.structure.ConcernEnum;
97  import coras.structure.SubProcessEnum;
98  import coras.structure.ViewpointEnum;
99  import coras.types.ElementTypeEnum;
100 import coras.types.IDocument;
101 import coras.types.IFaultTree;
102 import coras.types.ITable;
103 import coras.types.IUMLModel;
104 /***
105  * @author fvr
106  *
107  * TODO To change the template for this generated type comment go to
108  * Window - Preferences - Java - Code Style - Code Templates
109  */
110 public class CorasClient implements Observer {
111 
112 	private CorasServices services = null; 
113 	private Properties properties = new Properties();
114 	private boolean showDeletedElements = false;
115 	
116     private RiskAnalysisProject project = null;
117     private ExperiencePackage experiencePackage = null;
118     private Object selectedProjectItem = null;
119     private Object selectedPackageItem = null;
120     
121     private DefaultTreeModel projectTreeModel = new DefaultTreeModel(new CorasTreeNode("No Project"));
122     private DefaultTreeModel packageTreeModel = new DefaultTreeModel(new CorasTreeNode("No Experience Package"));
123     private PackageFrame projectFrame = null;
124     private PackageFrame packageFrame = null;
125     private Map resultFramesMap = new HashMap();
126     private Map experienceFramesMap = new HashMap();
127     
128 	private ExitAction exitAction = new ExitAction(this);
129 	private GenerateReportAction generateReportAction = new GenerateReportAction(this);
130 	private NewProjectAction newProjectAction = new NewProjectAction(this);
131 	private NewExperiencePackageAction newExperiencePackageAction = new NewExperiencePackageAction(this);
132 	private ExportExperienceAsResultAction exportExperienceAsResultAction = new ExportExperienceAsResultAction(this);
133 	private OpenProjectAction openProjectAction = new OpenProjectAction(this);
134 	private OpenExperiencePackageAction openExperiencePackageAction = new OpenExperiencePackageAction(this);
135 	private CheckConsistencyAction checkConsistencyAction = new CheckConsistencyAction(this);
136 	private ExportResultAsExperienceAction exportResultAsExperienceAction = new ExportResultAsExperienceAction(this);
137     private OpenProjectItemAction openProjectItemAction = new OpenProjectItemAction(this);
138     private OpenPackageItemAction openPackageItemAction = new OpenPackageItemAction(this);
139     private DeleteProjectItemAction deleteProjectItemAction = new DeleteProjectItemAction(this);
140     private DeletePackageItemAction deletePackageItemAction = new DeletePackageItemAction(this);
141     private ImportExperiencePackageAction importExperiencePackageAction = new ImportExperiencePackageAction(this);
142     private ImportRiskAnalysisProjectAction importRiskAnalysisProjectAction = new ImportRiskAnalysisProjectAction(this);
143     private ExportExperiencePackageAction exportExperiencePackageAction = new ExportExperiencePackageAction(this);
144     private ExportRiskAnalysisProjectAction exportRiskAnalysisProjectAction = new ExportRiskAnalysisProjectAction(this);
145     private NewResultAction newCorasUmlModelAction = new NewResultAction(this, ElementTypeEnum.UML_MODEL, CorasTreeCellRenderer.UML_ICON);
146     private NewResultAction newTableAction = new NewResultAction(this, ElementTypeEnum.TABLE, CorasTreeCellRenderer.TABLE_ICON);
147     private ImportResultFromFileAction importUmlModelAction = new ImportResultFromFileAction(this, ElementTypeEnum.UML_MODEL, CorasTreeCellRenderer.UML_ICON);
148     private ImportResultFromFileAction importFaultTreeAction = new ImportResultFromFileAction(this, ElementTypeEnum.FAULT_TREE, CorasTreeCellRenderer.FAULT_TREE_ICON);
149     private ImportResultFromFileAction importDocumentAction = new ImportResultFromFileAction(this, ElementTypeEnum.DOCUMENT, CorasTreeCellRenderer.DOCUMENT_ICON);
150 
151 	private JMenu fileMenu = null;
152 	private JMenu newMenu = null;
153 	private JMenu openMenu = null;
154 	private JMenu importMenu = null;
155 	private JMenu exportMenu = null;
156 	private JMenu helpMenu = null;
157 	private JMenuItem helpStartedMenuItem = null;
158 	private JMenuItem helpAboutMenuItem = null;
159 	private JMenuItem helpMethodologyMenuItem = null;
160 	private JMenuItem helpContentsMenuItem = null;
161 
162     private JPopupMenu projectPopupMenu = null;
163 	private JMenu projectNewMenu = null;
164 	private JMenu projectImportMenu = null;
165 	private JPopupMenu subprocessPopupMenu = null;
166 	private JMenu subprocessNewMenu = null;
167 	private JMenu subprocessImportMenu = null;
168 	private JPopupMenu resultPopupMenu = null;
169 	private JPopupMenu packagePopupMenu = null;
170 	private JPopupMenu experiencePopupMenu = null;
171 
172 	private JMenu deleteMenu = null;
173 	private JMenuItem[] openRecentProjectMenuItems = new JMenuItem[4];
174 	private ArrayList recentProjectIds = new ArrayList(4);
175 	private ArrayList recentProjectNames = new ArrayList(4);
176 	
177 	private CorasFrame mainFrame = null;
178 	
179 	public static void main(String[] args) {
180 		URL authURL = CorasClient.class.getClassLoader().getResource("auth.conf");
181 		String authLocation = (authURL != null ? authURL.toString() : "auth.conf");
182 		System.setProperty("java.security.auth.login.config", authLocation);
183 		CorasClient client = new CorasClient();
184 	}
185 	/***
186 	 * This is the default constructor
187 	 */
188 	public CorasClient() {
189 		super();
190 		initialize();
191 		loadProperties();
192 		updateActions();
193 		setSelectedProjectItem(null);
194 		setSelectedPackageItem(null);
195 		mainFrame.setVisible(true);
196 	}
197 	
198 	/* (non-Javadoc)
199 	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
200 	 */
201 	public void update(Observable o, Object arg) {
202 	    if (o instanceof RiskAnalysisProject) {
203 	        updateProject(null);
204 	    } else if (o instanceof ExperiencePackage) {
205 	        updatePackage(null);
206 	    }
207 	}
208 	
209 	protected CorasServices getCorasServices() {
210 		return services;
211 	}
212 	
213 	protected CorasFrame getMainFrame() {
214 		return mainFrame;
215 	}
216 	
217 	protected RiskAnalysisProject getProject() {
218 		return project;
219 	}
220 	
221 	protected ExperiencePackage getExperiencePackage() {
222 		return experiencePackage;
223 	}
224 
225 	protected Object getSelectedProjectItem() {
226 		return selectedProjectItem;
227 	}
228 	
229 	protected void addResultFrame(JInternalFrame resultFrame) {
230 		getMainFrame().getProjectPanel().addInternalFrame(resultFrame);
231 	}
232 	
233 	protected synchronized boolean closeProject() {
234 		return closeProjectFrame() && closeAllResults();
235 	}
236 	
237 	/***
238 	 * 
239 	 */
240 	protected void quit() {
241 	    if (closeProject() && closePackage()) {
242 	        int result = JOptionPane.showConfirmDialog(getMainFrame(), 
243 	                "Are you sure you wish to quit?",
244 	                "Quit CORAS Tool", 
245 	                JOptionPane.YES_NO_OPTION);
246 	        if (result == JOptionPane.NO_OPTION) {
247 	            return;
248 	        }
249 		    if (project != null) {
250 		    	addRecentProject(project.getId(), project.getName());
251 		    }
252 	        getMainFrame().dispose();
253 	        storeProperties();
254 	        System.exit(0);
255 	    }
256 	}
257 	
258 	/***
259 	 * @return
260 	 */
261 	protected boolean openProject() {
262 		if (!closeProject()) {
263 			return false;
264 		}
265 		OpenProjectDialog dialog = new OpenProjectDialog(getMainFrame());
266 		dialog.setLocationRelativeTo(getMainFrame());
267 		dialog.setVisible(true);
268 		if (dialog.getResult() == JOptionPane.CANCEL_OPTION) {
269 			return false;
270 		}
271 		RiskAnalysisProject newProject = dialog.getSelectedProject();
272 		setProject(newProject);
273 		return true;
274 	}
275 	
276 	/***
277 	 * @return
278 	 */
279 	protected boolean openExperiencePackage() {
280 		if (!closePackage()) {
281 			return false;
282 		}
283 		OpenPackageDialog dialog = new OpenPackageDialog(getMainFrame());
284 		dialog.setLocationRelativeTo(getMainFrame());
285 		dialog.setVisible(true);
286 		if (dialog.getResult() == JOptionPane.CANCEL_OPTION) {
287 			return false;
288 		}
289 		ExperiencePackage _package = dialog.getSelectedPackage();
290 		setPackage(_package);
291 		return true;
292 	}
293 	
294 	protected boolean createNewProject() {
295 	    if (!closeProject()) {
296 	        return false;
297 	    }
298 	    NewPackageDialog dialog = new NewPackageDialog(getMainFrame());
299 	    dialog.setTitle("New Risk Analysis Project");
300 	    dialog.setCategoryEnabled(false);
301 	    dialog.setDomainEnabled(false);
302 	    dialog.setLocationRelativeTo(getMainFrame());
303 	    dialog.setVisible(true);
304 	    if (dialog.getResult() == JOptionPane.CANCEL_OPTION) {
305 	        return false;
306 	    }
307 	    String name = dialog.getProjectName();
308 	    String shortDescription = dialog.getShortDescription();
309 	    String fullDescription = dialog.getFullDescription();
310 	    RiskAnalysisProject project = RiskAnalysisProject.createProject(name, shortDescription, fullDescription);
311 	    if (project == null) {
312 	        // FIXME user feedback
313 	        return false;
314 	    } else {
315 	        setProject(project);
316 	        return true;
317 	    }
318 	}
319 	
320 	/***
321 	 * @return
322 	 */
323 	protected boolean createNewPackage() {
324 		if (!closePackage()) {
325 			return false;
326 		}
327 		NewPackageDialog dialog = new NewPackageDialog(getMainFrame());
328 		dialog.setTitle("New Experience Package");
329 		dialog.setLocationRelativeTo(getMainFrame());
330 		dialog.setVisible(true);
331 		if (dialog.getResult() == JOptionPane.CANCEL_OPTION) {
332 			return false;
333 		}
334 		String name = dialog.getProjectName();
335 		String shortDescription = dialog.getShortDescription();
336 		String fullDescription = dialog.getFullDescription();
337 		CategoryEnum category = dialog.getCategory();
338 		String domain = dialog.getDomain();
339 		ExperiencePackage newPackage = ExperiencePackage.createPackage(name, shortDescription, category, domain, fullDescription);
340 		if (newPackage == null) {
341 		    // FIXME user feedback
342 		    return false;
343 		} else {
344 		    setPackage(newPackage);
345 		    return true;
346 		}
347 	}
348 	
349 	protected synchronized void setProject(RiskAnalysisProject newProject) {
350 	    if (project == newProject) {
351 	        return;
352 	    }
353 	    if (project != null) {
354 	        project.deleteObserver(this);
355 	        addRecentProject(project.getId(), project.getName());
356 	    }
357 	    project = newProject;
358 	    if (project != null) {
359 	        project.addObserver(this);
360 	    }
361 	    updateProject("Opening project");
362 	    getMainFrame().showProjectPanel();
363 	    updateActions();
364 	}
365 	
366 	/***
367 	 * @return
368 	 */
369 	protected RiskAnalysisResult getSelectedResult() {
370 	    Object item = selectedProjectItem;
371 	    if (item instanceof RiskAnalysisResult) {
372 	        return (RiskAnalysisResult) item;
373 	    } else {
374 	        return null;
375 	    }
376 	}
377 	
378 	/***
379 	 * @return
380 	 */
381 	protected Experience getSelectedExperience() {
382 	    Object item = selectedPackageItem;
383 	    if (item instanceof Experience) {
384 	        return (Experience) item;
385 	    } else {
386 	        return null;
387 	    }
388 	}
389 	
390 	/***
391 	 * 
392 	 */
393 	protected void openSelectedProjectItem() {
394 	    Object item = selectedProjectItem;
395 	    getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
396 	    if (item instanceof RiskAnalysisProject) {
397 	        openPackageFrame(project, getMainFrame().getProjectPanel(), projectFrame);
398 	    } else if (item instanceof RiskAnalysisResult) {
399 	    	openProjectItem(getSelectedResult());
400 	    }
401 	    getMainFrame().setCursor(Cursor.getDefaultCursor());
402 	}
403 	
404 	protected void openProjectItem(RiskAnalysisResult result) {
405 		ElementFrame frame = (ElementFrame) resultFramesMap.get(result.getId());
406 		openElementFrame(result, getMainFrame().getProjectPanel(), frame);
407 	}
408 	
409 	/***
410 	 * 
411 	 */
412 	protected void openSelectedPackageItem() {
413 	    Object item = selectedPackageItem;
414 	    getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
415 	    if (item instanceof ExperiencePackage) {
416 	        openPackageFrame(experiencePackage, getMainFrame().getLibraryPanel(), packageFrame);
417 	    } else if (item instanceof Experience) {
418 	        Experience experience = getSelectedExperience();
419 	        ElementFrame frame = (ElementFrame) experienceFramesMap.get(experience.getId());
420 	        openElementFrame(experience, getMainFrame().getLibraryPanel(), frame);
421 	    }
422 	    getMainFrame().setCursor(Cursor.getDefaultCursor());
423 	}
424 	
425 	/***
426 	 * 
427 	 */
428 	protected void deleteSelectedProjectItem() {
429 	    Object item = selectedProjectItem;
430 	    if (item instanceof RiskAnalysisProject) {
431 	    	// DO NOTHING
432 	    } else if (item instanceof RiskAnalysisResult) {
433 	        RiskAnalysisResult result = getSelectedResult();
434 	        ElementFrame frame = (ElementFrame) resultFramesMap.get(result.getId());
435 	        if (deleteElement(result, getMainFrame().getProjectPanel(), frame)) {
436 	        	updateProject(null);
437 	        }
438 	    }
439 	}
440 	
441 	/***
442 	 * 
443 	 */
444 	protected void deleteSelectedPackageItem() {
445 	    Object item = selectedPackageItem;
446 	    if (item instanceof ExperiencePackage) {
447 	    	// DO NOTHING
448 	    } else if (item instanceof Experience) {
449 	        Experience experience = getSelectedExperience();
450 	        ElementFrame frame = (ElementFrame) experienceFramesMap.get(experience.getId());
451 	        if (deleteElement(experience, getMainFrame().getLibraryPanel(), frame)) {
452 	        	updatePackage(null);
453 	        }
454 	    }
455 	}
456 	
457 	private void initialize() {
458 		mainFrame = new CorasFrame();
459 		mainFrame.addWindowListener(new java.awt.event.WindowAdapter() {   
460 			public void windowOpened(java.awt.event.WindowEvent e) {    
461 				login();
462 				showStartupWizard();
463 			} 
464 			public void windowClosing(java.awt.event.WindowEvent e) {    
465 				quit();
466 			}
467 		});
468 		JMenuBar menuBar = mainFrame.getJMenuBar();
469 		menuBar.add(getFileMenu());
470 		menuBar.add(getHelpMenu());
471 		
472 		mainFrame.getProjectPanel().setTreeModel(projectTreeModel);
473 		mainFrame.getProjectPanel().addTreeSelectionListener(new TreeSelectionListener() {
474             public void valueChanged(TreeSelectionEvent e) {
475                 if (e.isAddedPath()) {
476                     TreePath path = e.getPath();
477                     DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
478                     setSelectedProjectItem(node.getUserObject());
479                 } else {
480                     setSelectedProjectItem(null);
481                 }
482             }
483 		});
484 		mainFrame.getProjectPanel().addTreeMouseListener(new MouseAdapter() {
485 			public void mousePressed(java.awt.event.MouseEvent e) {
486 			    Component component = e.getComponent();
487 			    if (component instanceof JTree) {
488 			        JTree tree = (JTree) component;
489 			        TreePath path = tree.getPathForLocation(e.getX(), e.getY());
490 			        if (path != null) {
491 			            tree.setSelectionPath(path);
492 			            if (e.getClickCount() == 2) {
493 			                openSelectedProjectItem();
494 			            }
495 			        }
496 			    }
497 			    if (e.isPopupTrigger()) {
498 			        openContextMenu(e.getComponent(), e.getX(), e.getY());
499 			    }
500 			}
501 			public void mouseReleased(java.awt.event.MouseEvent e) {
502 			    if (e.isPopupTrigger()) {
503 			        openContextMenu(e.getComponent(), e.getX(), e.getY());
504 			    }
505 			}
506 		});
507 
508 		mainFrame.getLibraryPanel().setTreeModel(packageTreeModel);
509 		mainFrame.getLibraryPanel().addTreeSelectionListener(new TreeSelectionListener() {
510             public void valueChanged(TreeSelectionEvent e) {
511                 if (e.isAddedPath()) {
512                     TreePath path = e.getPath();
513                     DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
514                     setSelectedPackageItem(node.getUserObject());
515                 } else {
516                     setSelectedPackageItem(null);
517                 }
518             }
519 		});
520 		mainFrame.getLibraryPanel().addTreeMouseListener(new MouseAdapter() {
521 			public void mousePressed(java.awt.event.MouseEvent e) {
522 			    Component component = e.getComponent();
523 			    if (component instanceof JTree) {
524 			        JTree tree = (JTree) component;
525 			        TreePath path = tree.getPathForLocation(e.getX(), e.getY());
526 			        if (path != null) {
527 			            tree.setSelectionPath(path);
528 			            if (e.getClickCount() == 2) {
529 			                openSelectedPackageItem();
530 			            }
531 			        }
532 			    }
533 			    if (e.isPopupTrigger()) {
534 			        openContextMenu(e.getComponent(), e.getX(), e.getY());
535 			    }
536 			}
537 			public void mouseReleased(java.awt.event.MouseEvent e) {
538 			    if (e.isPopupTrigger()) {
539 			        openContextMenu(e.getComponent(), e.getX(), e.getY());
540 			    }
541 			}
542 		});
543 
544 		mainFrame.getTabbedPane().addChangeListener(new javax.swing.event.ChangeListener() { 
545 			public void stateChanged(javax.swing.event.ChangeEvent e) {
546 			    updateActions();
547 //			    updateTabColors();
548 			}
549 		});
550 
551 	}
552 
553 	private void login() {
554 		LoginDialog loginDialog = new LoginDialog(getMainFrame());
555 		LoginContext lc = null;
556 		try {
557 			lc = new LoginContext("coras", loginDialog);
558 			loginDialog.setLoginContext(lc);
559 			loginDialog.setLocationRelativeTo(getMainFrame());
560 			loginDialog.setVisible(true);
561 		} catch (LoginException e) {
562 			e.printStackTrace();
563 		}
564 		if (!loginDialog.loginSucceeded()) {
565 			JOptionPane.showMessageDialog(getMainFrame(),
566 					"Login failed, program exiting.", 
567 					"Login failed", 
568 					JOptionPane.ERROR_MESSAGE);
569 			System.exit(1);
570 		}
571 		String hostname = loginDialog.getHostname();
572 		int port = loginDialog.getPort();
573 		Asset.setJndiUrl(hostname, port);
574 		try {
575 			String jndiUrl = "jnp://" + hostname + ":" + port;
576 			Hashtable environment = new Hashtable();
577 			environment.put("java.naming.provider.url", jndiUrl);
578 			services = CorasServicesUtil.getHome(environment).create();
579 		} catch (Exception e) {
580 			e.printStackTrace();
581 			System.exit(1);
582 		}
583 		lc = null;
584 	}
585 	
586 	/***
587 	 * 
588 	 */
589 	private void showStartupWizard() {
590 		boolean finished = false;
591 		while (!finished) {
592 			StartupWizard wizard = new StartupWizard(getMainFrame());
593 			wizard.setLocationRelativeTo(getMainFrame());
594 			wizard.setVisible(true);
595 			switch (wizard.getResult()) {
596 				case StartupWizard.CREATE_PROJECT :
597 					if (createNewProject()) {
598 						finished = true;
599 					}
600 					break;
601 				case StartupWizard.OPEN_PROJECT :
602 					if (openProject()) {
603 						finished = true;
604 					}
605 					break;
606 				case StartupWizard.START_USING :
607 				    finished = true;
608 				    break;
609 				case StartupWizard.QUIT :
610 					quit();
611 					break;
612 				default :
613 					break;
614 			}
615 		}
616 	}
617 	
618 	private File getPropertiesFile() {
619     	File homeDir = new File(System.getProperty("user.home"));
620     	File corasDir = new File(homeDir, ".coras");
621     	if (corasDir.exists() || corasDir.mkdirs()) {
622     		return new File(corasDir, "coras.properties");
623     	} else {
624     		return null;
625     	}
626 	}
627 
628 	private void loadProperties() {
629 		File propertiesFile = getPropertiesFile();
630     	if (propertiesFile != null) {
631     		if (!propertiesFile.exists()) {
632     			// Do nothing
633     		} else if (!propertiesFile.canRead()) {
634     				System.err.println("Cannot read properties file: " + propertiesFile.getAbsolutePath());
635     		} else {
636     			try {
637     				properties.load(new FileInputStream(propertiesFile));
638     				String dir = properties.getProperty("defaultDir");
639     				if (dir != null && !dir.matches("//s*")) IOUtils.setDefaultDir(new File(dir));
640     				for (int i = 4; i >= 0; i--) {
641     					String recentProjectId = properties.getProperty("recentProjectId_" + i);
642     					if (recentProjectId != null && !recentProjectId.matches("//s*")) {
643     						String recentProjectName = properties.getProperty("recentProjectName_" + i);
644     						addRecentProject(recentProjectId, recentProjectName);
645     					}
646     				}
647     			} catch (Exception e) {
648     				System.err.println("Error reading properties file: " + e.getMessage());
649     			}
650     		}
651     	} else {
652     		System.err.println("Unable to find or create coras directory: " + System.getProperty("user.home") + File.separatorChar + ".coras");
653     	}
654 	}
655 
656 	private void storeProperties() {
657 		File propertiesFile = getPropertiesFile();
658     	if (propertiesFile != null) {
659     		if (propertiesFile.exists() && !propertiesFile.canWrite()) {
660     			System.err.println("Cannot write to properties file: " + propertiesFile.getAbsolutePath());
661     		} else if (!propertiesFile.getParentFile().canWrite()) {
662     			System.err.println("Cannot write to coras directory: " + propertiesFile.getParentFile().getAbsolutePath());
663     		} else {
664     			try {
665     				File dir = IOUtils.getDefaultDir();
666     				properties.setProperty("defaultDir", dir != null ? dir.getAbsolutePath() : null);
667 					for (int i = 0; i < recentProjectIds.size(); i++) {
668 						String projectId = (String) recentProjectIds.get(i);
669 						String projectName = (String) recentProjectNames.get(i);
670 						properties.setProperty("recentProjectId_" + i, projectId);
671 						properties.setProperty("recentProjectName_" + i, projectName);
672 					}
673 					properties.store(new FileOutputStream(propertiesFile), "CORAS Tool properties");
674 				} catch (Exception e) {
675 					System.err.println("Error writing properties file: " + e.getMessage());
676 				}
677     		}
678     	} else {
679     		System.err.println("Unable to find or create coras directory: " + System.getProperty("user.home") + File.separatorChar + ".coras");
680     	}
681 	}
682 	
683 	private void addRecentProject(String projectId, String projectName) {
684     	int index = recentProjectIds.indexOf(projectId);
685     	if (index != -1) {
686     		recentProjectIds.remove(index);
687     		recentProjectNames.remove(index);
688     	}
689     	while (recentProjectIds.size() >= 4) {
690     		recentProjectIds.remove(3);
691     		recentProjectNames.remove(3);
692     	}
693    		recentProjectIds.add(0, projectId);
694    		recentProjectNames.add(0, projectName);
695 		for (int i = 0; i < 4; i++) {
696 			if (i < recentProjectIds.size()) {
697 				projectId = (String) recentProjectIds.get(i);
698 				projectName = (String) recentProjectNames.get(i);
699 				AbstractAction action = new OpenRecentProjectAction(this, projectId, projectName, i + 1);
700 				JMenuItem item = openRecentProjectMenuItems[i];
701 				item.setAction(action);
702 				item.setVisible(true);
703 				// item.setEnabled(true);
704 			}
705 		}
706     }
707     
708     private synchronized boolean closeProjectFrame() {
709         if (closeInternalFrame(project, getMainFrame().getProjectPanel(), projectFrame)) {
710             projectFrame = null;
711             return true;
712         } else {
713             return false;
714         }
715     }
716     
717     private synchronized boolean closeAllResults() {
718         if (project != null) {
719         	ArrayList frameIds = new ArrayList(resultFramesMap.keySet());
720             for (Iterator i = frameIds.iterator(); i.hasNext(); ) {
721             	String id = (String) i.next();
722                 RiskAnalysisResult result = project.getResult(id);
723                 if (!closeResult(result)) {
724                     return false;
725                 }
726             }
727         }
728         return true;
729     }
730 
731     private synchronized boolean closePackage() {
732         return closePackageFrame() && closeAllExperiences();
733     }
734     
735     private synchronized boolean closePackageFrame() {
736         if (closeInternalFrame(experiencePackage, getMainFrame().getLibraryPanel(), packageFrame)) {
737             packageFrame = null;
738             return true;
739         } else {
740             return false;
741         }
742     } 
743     
744     private synchronized boolean closeAllExperiences() {
745         if (experiencePackage != null) {
746         	ArrayList frames = new ArrayList(experienceFramesMap.keySet());
747             for (Iterator i = frames.iterator(); i.hasNext(); ) {
748             	String id = (String) i.next();
749                 Experience experience = experiencePackage.getExperience(id);
750                 if (!closeExperience(experience)) {
751                     return false;
752                 }
753             }
754         }
755         return true;
756     }
757     
758     private synchronized boolean closeResult(RiskAnalysisResult result) {
759         ElementFrame resultFrame = (ElementFrame) resultFramesMap.get(result.getId());
760         if (closeInternalFrame(result, getMainFrame().getProjectPanel(), resultFrame)) {
761             resultFramesMap.remove(result.getId());
762             return true;
763         } else {
764             return false;
765         }
766     } 
767     
768     private synchronized boolean closeExperience(Experience experience) {
769         ElementFrame experienceFrame = (ElementFrame) experienceFramesMap.get(experience.getId());
770         if (closeInternalFrame(experience, getMainFrame().getLibraryPanel(), experienceFrame)) {
771             experienceFramesMap.remove(experience.getId());
772             return true;
773         } else {
774             return false;
775         }
776     }
777     
778     private synchronized boolean closeInternalFrame(CorasPackage thePackage, final PackagePanel panel, final PackageFrame frame) { 
779         if (!handleSaveChanges(thePackage, frame, true)) {
780             return false;
781         }
782         if (frame != null) {
783             SwingUtilities.invokeLater(new Runnable() {
784                 public void run() {
785                     frame.setVisible(false);
786                     panel.removeInternalFrame(frame);
787                     frame.dispose();
788                 }
789             });
790         }
791         return true;
792     }
793     
794     private synchronized boolean closeInternalFrame(CorasElement element, final PackagePanel panel, final ElementFrame frame) {
795     	if (frame.isEditing() && frame.isOpenExternal()) {
796             int option = JOptionPane.showConfirmDialog(getMainFrame(), 
797             		"<HTML><P>" + element.getType() + " " + element.getName() + " is being edited in an external application.</P><P>Close anyway (external changes will be lost)?</P></HTML>", 
798             		"Really close?", JOptionPane.YES_NO_OPTION);
799             if (option == JOptionPane.NO_OPTION) {
800             	return false;
801             }
802     	}
803         if (!handleSaveChanges(element, frame, true, true)) {
804             return false;
805         }
806         if (frame != null) {
807             SwingUtilities.invokeLater(new Runnable() {
808                 public void run() {
809                     frame.setVisible(false);
810                     panel.removeInternalFrame(frame);
811                     frame.dispose();
812                 }
813             });
814         }
815         return true;
816     }
817     
818     private synchronized boolean handleSaveChanges(CorasPackage thePackage, PackageFrame frame, boolean enableDiscard) {
819         if (thePackage == null || frame == null || !frame.isEditing()) {
820             return true;
821         }
822         if (!frame.isDirty()) {
823         	return discardChanges(thePackage, frame);
824         }
825         SaveVersionDialog dialog = new SaveVersionDialog(getMainFrame());
826         dialog.setDiscardEnabled(enableDiscard);
827         dialog.setLocationRelativeTo(getMainFrame());
828         dialog.setVisible(true);
829         int result = dialog.getResult();
830         String annotation = dialog.getComment();
831         switch (result) {
832         case SaveVersionDialog.CANCEL :
833             return false;
834         case SaveVersionDialog.SAVE :
835             return saveVersion(thePackage, frame, annotation);
836         case SaveVersionDialog.DISCARD :
837             return discardChanges(thePackage, frame);
838 		default:
839 			// LOGGER.warn("This should never happen!");
840 			return true; // FIXME: This should never happen!
841         }
842     }
843 
844     private synchronized boolean handleSaveChanges(CorasElement element, ElementFrame frame, boolean withComment, boolean enableDiscard) {
845         if (element == null || frame == null || !frame.isEditing()) {
846             return true;
847         }
848         if (!frame.isDirty()) {
849         	return discardChanges(element, frame);
850         }
851         String annotation = "";
852         int result = SaveVersionDialog.SAVE;
853         if (withComment) {
854         	SaveVersionDialog dialog = new SaveVersionDialog(getMainFrame());
855         	dialog.setAssetName(element.getName());
856         	dialog.setDiscardEnabled(enableDiscard);
857         	dialog.setLocationRelativeTo(getMainFrame());
858         	dialog.setVisible(true);
859         	result = dialog.getResult();
860         	annotation = dialog.getComment();
861         }
862         switch (result) {
863         case SaveVersionDialog.CANCEL :
864             return false;
865         case SaveVersionDialog.SAVE :
866             return saveVersion(element, frame, annotation);
867         case SaveVersionDialog.DISCARD :
868             return discardChanges(element, frame);
869 		default:
870 			// LOGGER.warn("This should never happen!");
871 			return true; // FIXME: This should never happen!
872         }
873     }
874 
875     /***
876      * 
877      */
878     private synchronized boolean saveVersion(CorasPackage _package, PackageFrame frame, String annotation) {
879         boolean result = false;
880         
881         getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
882         try {
883             String name = frame.getPackageName();
884             String shortDescription = frame.getShortDescription();
885             String domain = frame.getDomain();
886             String fullDescription = frame.getFullDescription();
887             
888             // This causes too many events...
889             _package.setName(name);
890             _package.setShortDescription(shortDescription);
891             if (_package instanceof ExperiencePackage) {
892                 ((ExperiencePackage)_package).setDomain(domain);
893             }
894             _package.setFullDescription(fullDescription);
895             _package.checkIn(annotation);
896 //            frame.setEditing(false);
897             result = true;
898         } catch (LockException e) {
899             // TODO Auto-generated catch block
900             e.printStackTrace();
901         }
902         getMainFrame().setCursor(Cursor.getDefaultCursor());
903         
904         return result;
905     }
906 
907     private synchronized boolean saveVersion(CorasElement element, ElementFrame frame, String annotation) {
908         boolean result = false;
909         
910         getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
911 		try {
912             String name = frame.getElementName();
913             String shortDescription = frame.getShortDescription();
914             ConcernEnum concern = frame.getConcern();
915             ViewpointEnum[] viewpoints = frame.getViewpoints();
916             String fullDescription = frame.getFullDescription();
917             
918             boolean subprocessChanged = false;
919             if (concern != element.getConcern()) {
920                 SubProcessEnum oldSubprocess = element.getConcern() != null ? element.getConcern().getSubProcess() : null;
921                 SubProcessEnum newSubprocess = concern != null ? concern.getSubProcess() : null;
922                 subprocessChanged = oldSubprocess != newSubprocess;
923             }
924             
925             if (element instanceof IUMLModel) {
926                 UMLModelRepresentation umlModel = (UMLModelRepresentation) frame.getRepresentation(RepresentationTypeEnum.XMI_LIGHT);
927                 DiagramRepresentation diagram = (DiagramRepresentation) frame.getRepresentation(RepresentationTypeEnum.IMAGE);
928                 ((IUMLModel)element).setUMLModel(umlModel);
929                 ((IUMLModel)element).setUMLDiagram(diagram);
930             } else if (element instanceof IFaultTree) {
931                 FaultTreeModel model = (FaultTreeModel) frame.getRepresentation(RepresentationTypeEnum.FAULT_TREE_MODEL);
932                 DiagramRepresentation diagram = (DiagramRepresentation) frame.getRepresentation(RepresentationTypeEnum.IMAGE);
933                 ((IFaultTree)element).setFaultTreeModel(model);
934                 ((IFaultTree)element).setFaultTreeDiagram(diagram);
935             } else if (element instanceof IDocument) {
936                 DocumentRepresentation document = (DocumentRepresentation) frame.getRepresentation(RepresentationTypeEnum.DOCUMENT);
937                 ((IDocument)element).setDocumentContent(document);
938             } else if (element instanceof ITable) {
939                 ((ITable)element).updateRepresentation();
940             }
941             
942             // FIXME This causes too many events...
943             element.setName(name);
944             element.setShortDescription(shortDescription);
945             element.setConcern(concern);
946             element.setViewpoints(viewpoints);
947             element.setFullDescription(fullDescription);
948             element.checkIn(annotation);
949 //            frame.setEditing(false);
950             if (subprocessChanged) {
951                 if (element instanceof RiskAnalysisResult) {
952                     updateProject(null);
953                 } else {
954                     updatePackage(null);
955                 }
956             }
957             result = true;
958         } catch (LockException e) {
959             // TODO Auto-generated catch block
960             e.printStackTrace();
961         }
962         getMainFrame().setCursor(Cursor.getDefaultCursor());
963         if (result == true) {
964         	frame.makeClean();
965         }
966         return result;
967     }
968     
969     private synchronized boolean discardChanges(CorasPackage _package, PackageFrame frame) {
970     	getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
971         try {
972             _package.unCheckOut();
973             // FIXME frame.makeClean() and remove setEditing(false)???
974             frame.setEditing(false);
975             return true;
976         } catch (LockException e) {
977             // TODO Auto-generated catch block
978             e.printStackTrace();
979             return false;
980         } finally {
981         	getMainFrame().setCursor(Cursor.getDefaultCursor());
982         }
983     }
984     
985     private synchronized boolean discardChanges(CorasElement element, ElementFrame frame) {
986     	getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
987         try {
988             element.unCheckOut();
989             // FIXME frame.makeClean() and remove setEditing(false)???
990             frame.setEditing(false);
991             return true;
992         } catch (LockException e) {
993             // TODO Auto-generated catch block
994             e.printStackTrace();
995             return false;
996         } finally {
997         	getMainFrame().setCursor(Cursor.getDefaultCursor());
998         }
999     }
1000     
1001     private synchronized void setPackage(ExperiencePackage newPackage) {
1002         if (experiencePackage == newPackage) {
1003             return;
1004         }
1005         if (experiencePackage != null) {
1006             experiencePackage.deleteObserver(this);
1007         }
1008         experiencePackage = newPackage;
1009         if (experiencePackage != null) {
1010             experiencePackage.addObserver(this);
1011         }
1012         updatePackage("Opening experience package");
1013         getMainFrame().showLibraryPanel();
1014         updateActions();
1015     }
1016 
1017     /***
1018      * 
1019      */
1020     private void updateProject(String jobName) {
1021 //        DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) projectTreeModel.getRoot();
1022     	getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1023         final RiskAnalysisProject theProject = project;
1024         if (theProject != null) {
1025         	final ProgressDialog dialog = jobName != null ? new ProgressDialog(getMainFrame()) : null;
1026         	SwingWorker worker = new SwingWorker() {
1027 				public Object construct() {
1028 					Collection elements = theProject.getResults(this);
1029 					updateTree(projectTreeModel, 
1030 							theProject, 
1031 							elements, 
1032 							getMainFrame().getProjectPanel());
1033 					return null;
1034 				}
1035 				public void finished() {
1036 					setFinished(true);
1037 					getMainFrame().setCursor(Cursor.getDefaultCursor());
1038 				}
1039         	};
1040         	if (dialog != null) {
1041         		dialog.setWorker(worker);
1042         		dialog.setCancellable(false);
1043         	}
1044         	worker.setJobName(jobName);
1045         	worker.setCurrentTask(jobName);
1046         	worker.start();
1047         	if (dialog != null) {
1048         		dialog.setVisible(true);
1049         	}
1050         } else {
1051         	updateTree(projectTreeModel, 
1052         			"No Project", 
1053         			Collections.EMPTY_LIST, 
1054         			getMainFrame().getProjectPanel());
1055         	getMainFrame().setCursor(Cursor.getDefaultCursor());
1056         }
1057     }
1058 
1059     /***
1060      * 
1061      */
1062     private void updatePackage(String jobName) {
1063 //        DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) packageTreeModel.getRoot();
1064     	getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1065         final ExperiencePackage thePackage = experiencePackage;
1066         if (thePackage != null) {
1067         	final ProgressDialog dialog = jobName != null ? new ProgressDialog(getMainFrame()) : null;
1068         	SwingWorker worker = new SwingWorker() {
1069 				public Object construct() {
1070 					Collection elements = thePackage.getExperiences(this);
1071 					updateTree(packageTreeModel, 
1072 							thePackage, 
1073 							elements, 
1074 							getMainFrame().getLibraryPanel());
1075 					return null;
1076 				}
1077 				public void finished() {
1078 					setFinished(true);
1079 					getMainFrame().setCursor(Cursor.getDefaultCursor());
1080 				}
1081         	};
1082         	if (dialog != null) {
1083         		dialog.setWorker(worker);
1084         		dialog.setCancellable(false);
1085         	}
1086         	worker.setJobName(jobName);
1087         	worker.setCurrentTask(jobName);
1088         	worker.start();
1089         	if (dialog != null) {
1090         		dialog.setVisible(true);
1091         	}
1092         } else {
1093         	updateTree(packageTreeModel, 
1094         			"No Experience Package", 
1095         			Collections.EMPTY_LIST, 
1096         			getMainFrame().getLibraryPanel());
1097         	getMainFrame().setCursor(Cursor.getDefaultCursor());
1098         }
1099     }
1100 
1101     /***
1102      * @param rootNode
1103      * @param elements
1104      */
1105     private void updateTree(final DefaultTreeModel model, final Object userObject, final Collection elements, final PackagePanel packagePanel) {
1106         SwingUtilities.invokeLater(new Runnable() {
1107             public void run() {
1108             	DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) model.getRoot();
1109             	rootNode.setUserObject(userObject);
1110             	// model.nodeChanged(rootNode);
1111             	
1112             	if (userObject instanceof String) {
1113             		for (int i = 0; i < rootNode.getChildCount(); i++) {
1114             			packageTreeModel.removeNodeFromParent((MutableTreeNode) rootNode.getFirstChild());
1115             		}
1116             		return;
1117             	}
1118             	
1119             	if (rootNode.getChildCount() == 0) {
1120             		for (Iterator i = SubProcessEnum.VALUES.iterator(); i.hasNext(); ) {
1121             			SubProcessEnum subprocess = (SubProcessEnum) i.next();
1122             			DefaultMutableTreeNode subprocessNode = new DefaultMutableTreeNode(subprocess);
1123             			model.insertNodeInto(subprocessNode, rootNode, rootNode.getChildCount());
1124             			packagePanel.makeVisible(subprocessNode);
1125             		}
1126             	}
1127             	
1128             	Collection treeElements = getTreeElements(rootNode);
1129             	Collection removedElements = new ArrayList(treeElements);
1130             	removedElements.removeAll(elements);
1131             	Collection addedElements = new ArrayList(elements);
1132             	addedElements.removeAll(treeElements);
1133             	
1134             	for (int i = 0; i < rootNode.getChildCount(); i++) {
1135             		DefaultMutableTreeNode subprocessNode = (DefaultMutableTreeNode) rootNode.getChildAt(i);
1136             		for (int j = subprocessNode.getChildCount() - 1; j >= 0; j--) {
1137             			DefaultMutableTreeNode elementNode = (DefaultMutableTreeNode) subprocessNode.getChildAt(j);
1138             			CorasElement element = (CorasElement) elementNode.getUserObject();
1139             			if (removedElements.contains(element) || 
1140             					(element.isDeleted() && !showDeletedElements)) {
1141             				model.removeNodeFromParent(elementNode);
1142             			} else {
1143             				SubProcessEnum subprocess = (SubProcessEnum) subprocessNode.getUserObject();
1144             				ConcernEnum concern = element.getConcern();
1145             				if (concern != null && subprocess != concern.getSubProcess()) {
1146             					DefaultMutableTreeNode newParent = (DefaultMutableTreeNode) rootNode.getChildAt(SubProcessEnum.VALUES.indexOf(concern.getSubProcess()));
1147             					model.removeNodeFromParent(elementNode);
1148             					model.insertNodeInto(elementNode, newParent, newParent.getChildCount());
1149             					packagePanel.makeVisible(elementNode);
1150             				}
1151             			}
1152             		}
1153             	}
1154             	
1155             	for (Iterator i = addedElements.iterator(); i.hasNext(); ) {
1156             		CorasElement element = (CorasElement) i.next();
1157             		if (element.isDeleted() && !showDeletedElements) {
1158             			continue;
1159             		}
1160             		DefaultMutableTreeNode subprocessNode;
1161             		ConcernEnum concern = element.getConcern();
1162             		if (concern != null) {
1163             			subprocessNode = (DefaultMutableTreeNode) rootNode.getChildAt(SubProcessEnum.VALUES.indexOf(concern.getSubProcess()));
1164             		} else {
1165             			subprocessNode = (DefaultMutableTreeNode) rootNode.getFirstChild();
1166             		}
1167             		CorasTreeNode elementNode = new CorasTreeNode(element);
1168             		model.insertNodeInto(elementNode, subprocessNode, subprocessNode.getChildCount());
1169             		packagePanel.makeVisible(elementNode);
1170             	}
1171             }
1172         });
1173     }
1174 
1175     /***
1176      * @param rootNode
1177      * @return
1178      */
1179     private Collection getTreeElements(DefaultMutableTreeNode rootNode) {
1180         ArrayList result = new ArrayList();
1181         for (int i = 0; i < rootNode.getChildCount(); i++) {
1182             DefaultMutableTreeNode subprocessNode = (DefaultMutableTreeNode) rootNode.getChildAt(i);
1183             for (int j = 0; j < subprocessNode.getChildCount(); j++) {
1184                 DefaultMutableTreeNode elementNode = (DefaultMutableTreeNode) subprocessNode.getChildAt(j);
1185                 Object o = elementNode.getUserObject();
1186                 if (o instanceof CorasElement) {
1187                     result.add(o); // TODO this should always be true!
1188                 }
1189             }
1190         }
1191         return result;
1192     }
1193 
1194     /***
1195      */
1196     private synchronized void openPackageFrame(final CorasPackage thePackage, final PackagePanel packagePanel, PackageFrame frame) {
1197         if (frame != null) {
1198     		// TODO handle change of project...
1199     		packagePanel.setActiveInternalFrame(frame);
1200     		return;
1201         } 
1202         if (thePackage == null) {
1203             // FIXME error
1204             return;
1205         }
1206         
1207         final PackageFrame newFrame = new PackageFrame(thePackage);
1208         if (thePackage instanceof RiskAnalysisProject) {
1209             projectFrame = newFrame;
1210         } else {
1211             packageFrame = newFrame;
1212         }
1213         newFrame.setTitle(thePackage.getName());
1214         newFrame.setCategoryEnabled(thePackage instanceof ExperiencePackage);
1215         newFrame.setDomainEnabled(thePackage instanceof ExperiencePackage);
1216     	newFrame.addInternalFrameListener(new InternalFrameAdapter() {
1217     		public void internalFrameClosing(javax.swing.event.InternalFrameEvent e) {
1218     		    if (thePackage instanceof RiskAnalysisProject) {
1219     		        closeProjectFrame();
1220     		    } else {
1221     		        closePackageFrame();
1222     		    }
1223     		}
1224     	});
1225     	/*
1226     	newFrame.addEditActionListener(new java.awt.event.ActionListener() { 
1227     		public void actionPerformed(java.awt.event.ActionEvent e) {    
1228     		    editPackage(thePackage, newFrame);
1229     		}
1230     	});
1231     	*/
1232     	newFrame.addSaveActionListener(new java.awt.event.ActionListener() { 
1233     		public void actionPerformed(java.awt.event.ActionEvent e) {    
1234     		    handleSaveChanges(thePackage, newFrame, false);
1235     		    attainLock(thePackage, newFrame);
1236     		}
1237     	});
1238     	packagePanel.addInternalFrame(newFrame);
1239     	newFrame.show();
1240     	
1241         attainLock(thePackage, newFrame);
1242     }
1243     
1244 	private void attainLock(final CorasPackage thePackage, final PackageFrame frame) {
1245 		boolean locked;
1246         try {
1247 			thePackage.checkOut();
1248 			locked = true;
1249 		} catch (AlreadyLockedException e) {
1250 			// There is only one PackageFrame per package, so this is a dead
1251 			// leftover lock which can safely be removed
1252 			locked = true;
1253 		} catch (LockedByOtherUserException e) {
1254 			String dateString = new SimpleDateFormat().format(e.getLockedDate().getTime());
1255 			JOptionPane.showMessageDialog(frame, "<HTML><P>The " + (thePackage instanceof RiskAnalysisProject ? "project" : "experience package") + " details are currently being edited by user '" + e.getLockedBy() + "' (opened at " + dateString + ")</P><P>Opening in read-only mode.</P></HTML>", "Opening in read-only mode", JOptionPane.INFORMATION_MESSAGE);
1256 			locked = false;
1257 		} catch (LockException e) {
1258 			JOptionPane.showMessageDialog(frame, "<HTML><P>The " + (thePackage instanceof RiskAnalysisProject ? "project" : "experience package") + " is locked: " + e.getMessage() + "</P><P>Opening in read-only mode.</P></HTML>", "Opening in read-only mode", JOptionPane.ERROR_MESSAGE);
1259 			locked = false;
1260 		}
1261         frame.setEditing(locked);
1262 	}
1263 
1264     /***
1265      * @param result
1266      * @param projectPanel2
1267      * @param frame
1268      */
1269     private synchronized void openElementFrame(final CorasElement element, final PackagePanel packagePanel, ElementFrame frame) {
1270         if (frame != null) {
1271     		// TODO handle change of project...
1272     		packagePanel.setActiveInternalFrame(frame);
1273     		return;
1274         } 
1275         if (element == null) {
1276             // FIXME error
1277             return;
1278         }
1279         
1280         final ElementFrame newFrame = new ElementFrame(element, services);
1281         if (element instanceof RiskAnalysisResult) {
1282             resultFramesMap.put(element.getId(), newFrame);
1283         } else {
1284             experienceFramesMap.put(element.getId(), newFrame);
1285         }
1286 		newFrame.setTitle(element.getName());
1287         newFrame.setCategoryEnabled(element instanceof Experience);
1288         newFrame.setDomainEnabled(element instanceof Experience);
1289         newFrame.setAllowMultipleViewpoints(element instanceof Experience);
1290     	newFrame.addInternalFrameListener(new InternalFrameAdapter() {
1291     		public void internalFrameClosing(javax.swing.event.InternalFrameEvent e) {
1292     		    if (element instanceof RiskAnalysisResult) {
1293     		        closeResult((RiskAnalysisResult) element);
1294     		    } else {
1295     		        closeExperience((Experience) element);
1296     		    }
1297     		}
1298     	});
1299     	/*
1300     	newFrame.addEditActionListener(new java.awt.event.ActionListener() { 
1301     		public void actionPerformed(java.awt.event.ActionEvent e) {    
1302     		    editElement(element, newFrame);
1303     		}
1304     	});
1305     	*/
1306     	newFrame.addSaveActionListener(new java.awt.event.ActionListener() { 
1307     		public void actionPerformed(java.awt.event.ActionEvent e) {
1308     			saveElementFrame(newFrame, element, false);
1309     		}
1310     	});
1311     	newFrame.addSaveWithCommentActionListener(new java.awt.event.ActionListener() { 
1312     		public void actionPerformed(java.awt.event.ActionEvent e) {   
1313     			saveElementFrame(newFrame, element, true);
1314     		}
1315     	});
1316     	packagePanel.addInternalFrame(newFrame);
1317     	newFrame.show();
1318     	
1319         attainLock(element, newFrame);
1320     }
1321     
1322     private void saveElementFrame(ElementFrame frame, CorasElement element, boolean withComment) {
1323 		if (frame.isEditing() && frame.isOpenExternal()) {
1324 			int option = JOptionPane.showConfirmDialog(getMainFrame(), 
1325 					"<HTML><P>" + element.getType() + " " + element.getName() + " is being edited in an external application.</P><P>Save anyway (external changes will be lost)?</P></HTML>", 
1326 					"Really save?", JOptionPane.YES_NO_OPTION);
1327 			if (option == JOptionPane.NO_OPTION) {
1328 				return;
1329 			}
1330 		}
1331 	    handleSaveChanges(element, frame, withComment, false);
1332 	    attainLock(element, frame);
1333     }
1334     
1335 	private void attainLock(final CorasElement element, final ElementFrame frame) {
1336 		boolean locked;
1337         try {
1338 			element.checkOut();
1339 			locked = true;
1340 		} catch (AlreadyLockedException e) {
1341 			// There is only one ElementFrame per element, so this is a dead
1342 			// leftover lock which can safely be removed
1343 			locked = true;
1344 		} catch (LockedByOtherUserException e) {
1345 			String dateString = new SimpleDateFormat().format(e.getLockedDate().getTime());
1346 			JOptionPane.showMessageDialog(getMainFrame(), "<HTML><P>The result is currently being edited by user '" + e.getLockedBy() + "' (opened at " + dateString + ")</P><P>Opening in read-only mode.</P></HTML>", "Opening in read-only mode", JOptionPane.WARNING_MESSAGE);
1347 			locked = false;
1348 		} catch (LockException e) {
1349 			JOptionPane.showMessageDialog(getMainFrame(), "<HTML><P>Result is locked: " + e.getMessage() + "</P><P>Opening in read-only mode.</P></HTML>", "Opening in read-only mode", JOptionPane.ERROR_MESSAGE);
1350 			locked = false;
1351 		}
1352 		frame.setEditing(locked);
1353 	}
1354 
1355     private boolean deleteElement(CorasElement element, PackagePanel panel, ElementFrame frame) {
1356     	if (element == null) {
1357     		// FIXME error
1358     		return false;
1359     	}
1360 
1361     	int result;
1362     	if (frame != null && frame.isEditing()) {
1363     		result = JOptionPane.showConfirmDialog(getMainFrame(), "Are you sure you wish to discard editing changes and delete?", "Delete '" + element.getName() + "'", JOptionPane.YES_NO_OPTION);
1364     	} else {
1365     		try {
1366     			element.checkOut();
1367     			result = JOptionPane.showConfirmDialog(getMainFrame(), "Are you sure?", "Delete '" + element.getName() + "'", JOptionPane.YES_NO_OPTION);
1368     		} catch (AlreadyLockedException e) {
1369     			// This is OK // FIXME should not happen!?
1370     			result = JOptionPane.YES_OPTION;
1371     		} catch (LockedByOtherUserException e) {
1372     			JOptionPane.showMessageDialog(getMainFrame(), "Element being editet by user " + e.getLockedBy() + ", please try again later.", "Unable to delete '" + element.getName() + "'", JOptionPane.WARNING_MESSAGE);
1373     			return false;
1374     		} catch (LockException e) {
1375     			// FIXME this should not happen!?
1376     			JOptionPane.showMessageDialog(getMainFrame(), "Error deleting element: " + e.getMessage(), "Error deleting '" + element.getName() + "'", JOptionPane.ERROR_MESSAGE);
1377     			return false;
1378     		}
1379     	}
1380     	if (result == JOptionPane.NO_OPTION) {
1381     		return false;
1382     	}
1383     	
1384     	try {
1385 			element.markAsDeleted();
1386 			if (frame != null) {
1387 				frame.doDefaultCloseAction();
1388 			}
1389 			return true;
1390 		} catch (LockException e) {
1391 			// FIXME this should not happen
1392 			e.printStackTrace();
1393 			return false;
1394 		}
1395     }
1396 
1397     /***
1398      * @param x
1399      * @param y
1400      */
1401     private void openContextMenu(Component c, int x, int y) {
1402         Component target = c.getComponentAt(x, y);
1403         if (target instanceof JTree) {
1404             JTree tree = (JTree) target;
1405             TreePath path = tree.getPathForLocation(x, y);
1406             if (path == null) {
1407                 return;
1408             }
1409             Object o = path.getLastPathComponent();
1410             if (o instanceof DefaultMutableTreeNode) {
1411                 DefaultMutableTreeNode node = (DefaultMutableTreeNode) o;
1412                 o = node.getUserObject();
1413                 if (o instanceof RiskAnalysisProject) {
1414                     getProjectPopupMenu().show(c, x, y);
1415                 } else if (o instanceof RiskAnalysisResult) {
1416                     getResultPopupMenu().show(c, x, y);
1417                 } else if (o instanceof ExperiencePackage) {
1418                     getPackagePopupMenu().show(c, x, y);
1419                 } else if (o instanceof Experience) {
1420                     getExperiencePopupMenu().show(c, x, y);
1421                 } else if (o instanceof SubProcessEnum) {
1422                     node = (DefaultMutableTreeNode) tree.getModel().getRoot();
1423                     o = node.getUserObject();
1424                     if (o instanceof RiskAnalysisProject) {
1425                         getSubprocessPopupMenu().show(c, x, y);
1426                     }
1427                 }
1428             }
1429         }
1430     }
1431     
1432     /***
1433      * @param result
1434      */
1435     private void setSelectedProjectItem(Object item) {
1436         selectedProjectItem = item;
1437         updateActions();
1438     }
1439 
1440     /***
1441      * @param experience
1442      */
1443     private void setSelectedPackageItem(Object item) {
1444         selectedPackageItem = item;
1445         updateActions();
1446     }
1447 
1448 	private void updateActions() {
1449 	    Component tab = getMainFrame().getTabbedPane().getSelectedComponent();
1450 	    
1451 	    newCorasUmlModelAction.setEnabled(tab == getMainFrame().getProjectPanel() && project != null);
1452 	    newTableAction.setEnabled(tab == getMainFrame().getProjectPanel() && project != null);
1453 	    importUmlModelAction.setEnabled(tab == getMainFrame().getProjectPanel() && project != null);
1454 	    importFaultTreeAction.setEnabled(tab == getMainFrame().getProjectPanel() && project != null);
1455 	    importDocumentAction.setEnabled(tab == getMainFrame().getProjectPanel() && project != null);
1456 	    deleteProjectItemAction.setEnabled(tab == getMainFrame().getProjectPanel() && selectedProjectItem instanceof RiskAnalysisResult);
1457 	    deletePackageItemAction.setEnabled(tab == getMainFrame().getLibraryPanel() && selectedPackageItem instanceof Experience);
1458 	    generateReportAction.setEnabled(tab == getMainFrame().getProjectPanel() && project != null);
1459 	    exportResultAsExperienceAction.setEnabled(tab == getMainFrame().getProjectPanel() && selectedProjectItem instanceof RiskAnalysisResult && ((RiskAnalysisResult)selectedProjectItem).getType() != ElementTypeEnum.TABLE);
1460 	    checkConsistencyAction.setEnabled(tab == getMainFrame().getProjectPanel() && selectedProjectItem instanceof RiskAnalysisResult);
1461 
1462 	    exportExperienceAsResultAction.setEnabled(tab == getMainFrame().getLibraryPanel() && selectedPackageItem instanceof Experience);
1463 	}
1464 	
1465 	/***
1466 	 * This method initializes jPopupMenu	
1467 	 * 	
1468 	 * @return javax.swing.JPopupMenu	
1469 	 */    
1470 	private JPopupMenu getProjectPopupMenu() {
1471 		if (projectPopupMenu == null) {
1472 			projectPopupMenu = new JPopupMenu();
1473 			projectPopupMenu.add(getProjectNewMenu());
1474 			projectPopupMenu.add(getProjectImportMenu());
1475 			projectPopupMenu.add(openProjectItemAction);
1476 			projectPopupMenu.add(generateReportAction);
1477 			projectPopupMenu.add(exportRiskAnalysisProjectAction);
1478 		}
1479 		return projectPopupMenu;
1480 	}
1481 	
1482 	/***
1483 	 * This method initializes jMenu	
1484 	 * 	
1485 	 * @return javax.swing.JMenu	
1486 	 */    
1487 	private JMenu getProjectNewMenu() {
1488 		if (projectNewMenu == null) {
1489 			projectNewMenu = new JMenu();
1490 			projectNewMenu.setText("New");
1491 			projectNewMenu.setMnemonic(java.awt.event.KeyEvent.VK_N);
1492 			projectNewMenu.add(newCorasUmlModelAction);
1493 			projectNewMenu.add(newTableAction);
1494 		}
1495 		return projectNewMenu;
1496 	}
1497 	
1498 	/***
1499 	 * This method initializes jMenu	
1500 	 * 	
1501 	 * @return javax.swing.JMenu	
1502 	 */    
1503 	private JMenu getProjectImportMenu() {
1504 		if (projectImportMenu == null) {
1505 			projectImportMenu = new JMenu();
1506 			projectImportMenu.setText("Import");
1507 			projectImportMenu.setMnemonic(java.awt.event.KeyEvent.VK_I);
1508 			projectImportMenu.add(importUmlModelAction);
1509 			projectImportMenu.add(importFaultTreeAction);
1510 			projectImportMenu.add(importDocumentAction);
1511 		}
1512 		return projectImportMenu;
1513 	}
1514 	
1515 	/***
1516 	 * This method initializes jPopupMenu	
1517 	 * 	
1518 	 * @return javax.swing.JPopupMenu	
1519 	 */    
1520 	private JPopupMenu getResultPopupMenu() {
1521 		if (resultPopupMenu == null) {
1522 			resultPopupMenu = new JPopupMenu();
1523 			resultPopupMenu.add(openProjectItemAction);
1524 			resultPopupMenu.add(checkConsistencyAction);
1525 			resultPopupMenu.add(exportResultAsExperienceAction);
1526 			resultPopupMenu.add(deleteProjectItemAction);
1527 		}
1528 		return resultPopupMenu;
1529 	}
1530 	
1531 	/***
1532 	 * This method initializes jPopupMenu	
1533 	 * 	
1534 	 * @return javax.swing.JPopupMenu	
1535 	 */    
1536 	private JPopupMenu getExperiencePopupMenu() {
1537 		if (experiencePopupMenu == null) {
1538 			experiencePopupMenu = new JPopupMenu();
1539 			experiencePopupMenu.add(openPackageItemAction);
1540 			experiencePopupMenu.add(exportExperienceAsResultAction);
1541 			experiencePopupMenu.add(deletePackageItemAction);
1542 		}
1543 		return experiencePopupMenu;
1544 	}
1545 	
1546 	/***
1547 	 * This method initializes jPopupMenu	
1548 	 * 	
1549 	 * @return javax.swing.JPopupMenu	
1550 	 */    
1551 	private JPopupMenu getPackagePopupMenu() {
1552 		if (packagePopupMenu == null) {
1553 			packagePopupMenu = new JPopupMenu();
1554 			packagePopupMenu.add(openPackageItemAction);
1555 			packagePopupMenu.add(exportExperiencePackageAction);
1556 		}
1557 		return packagePopupMenu;
1558 	}
1559 	
1560 	/***
1561 	 * This method initializes jPopupMenu	
1562 	 * 	
1563 	 * @return javax.swing.JPopupMenu	
1564 	 */    
1565 	private JPopupMenu getSubprocessPopupMenu() {
1566 		if (subprocessPopupMenu == null) {
1567 			subprocessPopupMenu = new JPopupMenu();
1568 			subprocessPopupMenu.add(getSubprocessNewMenu());
1569 			subprocessPopupMenu.add(getSubprocessImportMenu());
1570 		}
1571 		return subprocessPopupMenu;
1572 	}
1573 	
1574 	/***
1575 	 * This method initializes jMenu	
1576 	 * 	
1577 	 * @return javax.swing.JMenu	
1578 	 */    
1579 	private JMenu getSubprocessNewMenu() {
1580 		if (subprocessNewMenu == null) {
1581 			subprocessNewMenu = new JMenu();
1582 			subprocessNewMenu.setText("New");
1583 			subprocessNewMenu.setMnemonic(java.awt.event.KeyEvent.VK_N);
1584 			subprocessNewMenu.add(newCorasUmlModelAction);
1585 			subprocessNewMenu.add(newTableAction);
1586 		}
1587 		return subprocessNewMenu;
1588 	}
1589 	
1590 	/***
1591 	 * This method initializes jMenu	
1592 	 * 	
1593 	 * @return javax.swing.JMenu	
1594 	 */    
1595 	private JMenu getSubprocessImportMenu() {
1596 		if (subprocessImportMenu == null) {
1597 			subprocessImportMenu = new JMenu();
1598 			subprocessImportMenu.setText("Import");
1599 			subprocessImportMenu.setMnemonic(java.awt.event.KeyEvent.VK_N);
1600 			subprocessImportMenu.add(importUmlModelAction);
1601 			subprocessImportMenu.add(importFaultTreeAction);
1602 			subprocessImportMenu.add(importDocumentAction);
1603 		}
1604 		return subprocessImportMenu;
1605 	}
1606 	
1607 	/***
1608 	 * This method initializes jMenu	
1609 	 * 	
1610 	 * @return javax.swing.JMenu	
1611 	 */    
1612 	private JMenu getImportMenu() {
1613 		if (importMenu == null) {
1614 			importMenu = new JMenu();
1615 			importMenu.setText("Import");
1616 			importMenu.setMnemonic(java.awt.event.KeyEvent.VK_I);
1617 			importMenu.add(importUmlModelAction);
1618 			importMenu.add(importFaultTreeAction);
1619 			importMenu.add(importDocumentAction);
1620 			importMenu.addSeparator();
1621 			importMenu.add(importRiskAnalysisProjectAction);
1622 			importMenu.add(importExperiencePackageAction);
1623 		}
1624 		return importMenu;
1625 	}
1626 	
1627 	/***
1628 	 * This method initializes jMenu	
1629 	 * 	
1630 	 * @return javax.swing.JMenu	
1631 	 */    
1632 	private JMenu getExportMenu() {
1633 		if (exportMenu == null) {
1634 			exportMenu = new JMenu();
1635 			exportMenu.setText("Export");
1636 			exportMenu.setMnemonic(java.awt.event.KeyEvent.VK_E);
1637 			exportMenu.add(exportResultAsExperienceAction);
1638 			exportMenu.add(exportExperienceAsResultAction);
1639 			exportMenu.addSeparator();
1640 			exportMenu.add(exportRiskAnalysisProjectAction);
1641 			exportMenu.add(exportExperiencePackageAction);
1642 		}
1643 		return exportMenu;
1644 	}
1645 	
1646 	/***
1647 	 * This method initializes jMenu	
1648 	 * 	
1649 	 * @return javax.swing.JMenu	
1650 	 */    
1651 	private JMenu getDeleteMenu() {
1652 		if (deleteMenu == null) {
1653 			deleteMenu = new JMenu();
1654 			deleteMenu.setText("Delete");
1655 			deleteMenu.setMnemonic(java.awt.event.KeyEvent.VK_D);
1656 			deleteMenu.add(deleteProjectItemAction);
1657 			deleteMenu.add(deletePackageItemAction);
1658 		}
1659 		return deleteMenu;
1660 	}
1661 	
1662 	/***
1663 	 * This method initializes jMenuItem	
1664 	 * 	
1665 	 * @return javax.swing.JMenuItem	
1666 	 */    
1667 	private JMenuItem getHelpContentsMenuItem() {
1668 		if (helpContentsMenuItem == null) {
1669 			helpContentsMenuItem = new JMenuItem();
1670 			helpContentsMenuItem.setText("Help Contents");
1671 			helpContentsMenuItem.setMnemonic(java.awt.event.KeyEvent.VK_H);
1672 			helpContentsMenuItem.addActionListener(new ActionListener() {
1673 	            public void actionPerformed(ActionEvent e) {
1674 	                getMainFrame().getMethodologyPanel().showHelpID("top");
1675 	                getMainFrame().showMethodologyPanel();
1676 	            }
1677 			});
1678 		}
1679 		return helpContentsMenuItem;
1680 	}
1681 	
1682 	/***
1683 	 * This method initializes jMenuItem	
1684 	 * 	
1685 	 * @return javax.swing.JMenuItem	
1686 	 */    
1687 	private JMenuItem getHelpMethodologyMenuItem() {
1688 		if (helpMethodologyMenuItem == null) {
1689 			helpMethodologyMenuItem = new JMenuItem();
1690 			helpMethodologyMenuItem.setText("CORAS Methodology");
1691 			helpMethodologyMenuItem.setMnemonic(java.awt.event.KeyEvent.VK_C);
1692 			helpMethodologyMenuItem.addActionListener(new ActionListener() {
1693 	            public void actionPerformed(ActionEvent e) {
1694 	                getMainFrame().getMethodologyPanel().showHelpID("methodology");
1695 	                getMainFrame().showMethodologyPanel();
1696 	            }
1697 			});
1698 		}
1699 		return helpMethodologyMenuItem;
1700 	}
1701 	
1702 	/***
1703 	 * This method initializes jMenuItem	
1704 	 * 	
1705 	 * @return javax.swing.JMenuItem	
1706 	 */    
1707 	private JMenuItem getHelpAboutMenuItem() {
1708 		if (helpAboutMenuItem == null) {
1709 			helpAboutMenuItem = new JMenuItem();
1710 			helpAboutMenuItem.setText("About");
1711 			helpAboutMenuItem.setMnemonic(java.awt.event.KeyEvent.VK_A);
1712 			helpAboutMenuItem.addActionListener(new ActionListener() {
1713 	            public void actionPerformed(ActionEvent e) {
1714 	                getMainFrame().getMethodologyPanel().showHelpID("about");
1715 	                getMainFrame().showMethodologyPanel();
1716 	            }
1717 			});
1718 			/*
1719 			CSH.setHelpIDString(helpAboutMenuItem, "about_tool");
1720 			helpAboutMenuItem.addActionListener(new CSH.DisplayHelpFromSource(getMethodologyPanel().getHelpBroker()));
1721 			*/
1722 		}
1723 		return helpAboutMenuItem;
1724 	}
1725 	
1726 	/***
1727 	 * This method initializes jMenuItem	
1728 	 * 	
1729 	 * @return javax.swing.JMenuItem	
1730 	 */    
1731 	private JMenuItem getHelpStartedMenuItem() {
1732 		if (helpStartedMenuItem == null) {
1733 			helpStartedMenuItem = new JMenuItem();
1734 			helpStartedMenuItem.setText("Getting Started");
1735 			helpStartedMenuItem.setMnemonic(java.awt.event.KeyEvent.VK_G);
1736 			helpStartedMenuItem.addActionListener(new ActionListener() {
1737 	            public void actionPerformed(ActionEvent e) {
1738 	                getMainFrame().getMethodologyPanel().showHelpID("getting_started");
1739 	                getMainFrame().showMethodologyPanel();
1740 	            }
1741 			});
1742 			/*
1743 			CSH.setHelpIDString(helpStartedMenuItem, "getting_started");
1744 			helpStartedMenuItem.addActionListener(new CSH.DisplayHelpFromSource(getMethodologyPanel().getHelpBroker()));
1745 			*/
1746 		}
1747 		return helpStartedMenuItem;
1748 	}
1749 	
1750 	/***
1751 	 * This method initializes jMenu	
1752 	 * 	
1753 	 * @return javax.swing.JMenu	
1754 	 */    
1755 	private JMenu getHelpMenu() {
1756 		if (helpMenu == null) {
1757 			helpMenu = new JMenu();
1758 			helpMenu.setMnemonic(java.awt.event.KeyEvent.VK_H);
1759 			helpMenu.setText("Help");
1760 			helpMenu.add(getHelpContentsMenuItem());
1761 			helpMenu.add(getHelpStartedMenuItem());
1762 			helpMenu.add(getHelpMethodologyMenuItem());
1763 			helpMenu.addSeparator();
1764 			helpMenu.add(getHelpAboutMenuItem());
1765 		}
1766 		return helpMenu;
1767 	}
1768 	
1769 	/***
1770 	 * This method initializes jMenu	
1771 	 * 	
1772 	 * @return javax.swing.JMenu	
1773 	 */    
1774 	private JMenu getFileMenu() {
1775 		if (fileMenu == null) {
1776 			fileMenu = new JMenu();
1777 			fileMenu.setText("File");
1778 			fileMenu.setMnemonic(java.awt.event.KeyEvent.VK_F);
1779 			fileMenu.add(getNewMenu());
1780 			fileMenu.add(getOpenMenu());
1781 			fileMenu.add(getDeleteMenu());
1782 			fileMenu.addSeparator();
1783 			fileMenu.add(getImportMenu());
1784 			fileMenu.add(getExportMenu());
1785 			fileMenu.addSeparator();
1786 			fileMenu.add(generateReportAction);
1787 			fileMenu.add(checkConsistencyAction);
1788 			fileMenu.addSeparator();
1789 			for (int i = 0; i < 4; i++) {
1790 				JMenuItem item = new JMenuItem("" + (i+1), KeyEvent.VK_1 + i);
1791 				item.setEnabled(false);
1792 				item.setVisible(false);
1793 				openRecentProjectMenuItems[i] = item;
1794 				fileMenu.add(item);
1795 			}
1796 			fileMenu.addSeparator();
1797 			fileMenu.add(exitAction);
1798 		}
1799 		return fileMenu;
1800 	}
1801 	
1802 	/***
1803 	 * This method initializes jMenu	
1804 	 * 	
1805 	 * @return javax.swing.JMenu	
1806 	 */    
1807 	private JMenu getNewMenu() {
1808 		if (newMenu == null) {
1809 			newMenu = new JMenu();
1810 			newMenu.setText("New");
1811 			newMenu.setMnemonic(java.awt.event.KeyEvent.VK_N);
1812 			newMenu.add(newCorasUmlModelAction);
1813 			newMenu.add(newTableAction);
1814 			newMenu.addSeparator();
1815 			newMenu.add(newProjectAction);
1816 			newMenu.add(newExperiencePackageAction);
1817 		}
1818 		return newMenu;
1819 	}
1820 	
1821 	/***
1822 	 * This method initializes jMenu	
1823 	 * 	
1824 	 * @return javax.swing.JMenu	
1825 	 */    
1826 	private JMenu getOpenMenu() {
1827 		if (openMenu == null) {
1828 			openMenu = new JMenu();
1829 			openMenu.setText("Open");
1830 			openMenu.setMnemonic(java.awt.event.KeyEvent.VK_O);
1831 			openMenu.add(openProjectAction);
1832 			openMenu.add(openExperiencePackageAction);
1833 		}
1834 		return openMenu;
1835 	}
1836 	
1837 	private class CorasTreeNode extends DefaultMutableTreeNode implements Observer {
1838 	    /***
1839 	     * @param result
1840 	     */
1841 	    public CorasTreeNode(Object userObject) {
1842 	        super(userObject);
1843 	        if (userObject instanceof CorasAsset) {
1844 	            ((CorasAsset)userObject).addObserver(this);
1845 	        }
1846 	    }
1847 	
1848 	    public void setUserObject(Object userObject) {
1849 	        Object old = getUserObject();
1850 	        if (old instanceof CorasAsset) {
1851 	            ((CorasAsset)old).deleteObserver(this);
1852 	        }
1853 	        super.setUserObject(userObject);
1854 	        if (userObject instanceof CorasAsset) {
1855 	            ((CorasAsset)userObject).addObserver(this);
1856 	        }
1857 	        update(null, null);
1858 	    }
1859 	    
1860 	    public String toString() {
1861 	        Object o = getUserObject();
1862 	        if (o instanceof CorasAsset) {
1863 	            return ((CorasAsset)o).getName();
1864 	        } else {
1865 	            return super.toString();
1866 	        }
1867 	    }
1868 	
1869 	    /* (non-Javadoc)
1870 	     * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
1871 	     */
1872 	    public void update(Observable o, Object arg) {
1873 	        Object userObject = getUserObject();
1874 	        if (userObject instanceof RiskAnalysisProject || userObject instanceof RiskAnalysisResult) {
1875 	            projectTreeModel.nodeChanged(this);
1876 	        } else if (userObject instanceof ExperiencePackage || userObject instanceof Experience) {
1877 	            packageTreeModel.nodeChanged(this);
1878 	        }
1879 	    }
1880 	}
1881 	
1882 }