Source Code Cross Referenced for Organizer.java in  » Science » Cougaar12_4 » org » cougaar » tools » csmart » ui » viewer » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » Cougaar12_4 » org.cougaar.tools.csmart.ui.viewer 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * <copyright>
0003:         *  
0004:         *  Copyright 2000-2004 BBNT Solutions, LLC
0005:         *  under sponsorship of the Defense Advanced Research Projects
0006:         *  Agency (DARPA).
0007:         * 
0008:         *  You can redistribute this software and/or modify it under the
0009:         *  terms of the Cougaar Open Source License as published on the
0010:         *  Cougaar Open Source Website (www.cougaar.org).
0011:         * 
0012:         *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0013:         *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0014:         *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0015:         *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0016:         *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0017:         *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0018:         *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0019:         *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0020:         *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0021:         *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0022:         *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0023:         *  
0024:         * </copyright>
0025:         */
0026:
0027:        package org.cougaar.tools.csmart.ui.viewer;
0028:
0029:        import org.cougaar.tools.csmart.core.db.CommunityDbUtils;
0030:        import org.cougaar.tools.csmart.core.db.DBConflictHandler;
0031:        import org.cougaar.tools.csmart.core.db.DBUtils;
0032:        import org.cougaar.tools.csmart.core.db.ExperimentDB;
0033:        import org.cougaar.tools.csmart.core.db.PDbBase;
0034:        import org.cougaar.tools.csmart.core.db.PopulateDb;
0035:        import org.cougaar.tools.csmart.core.property.ModifiableComponent;
0036:        import org.cougaar.tools.csmart.core.property.ModificationEvent;
0037:        import org.cougaar.tools.csmart.core.property.ModificationListener;
0038:        import org.cougaar.tools.csmart.experiment.DBExperiment;
0039:        import org.cougaar.tools.csmart.experiment.Experiment;
0040:        import org.cougaar.tools.csmart.recipe.RecipeComponent;
0041:        import org.cougaar.tools.csmart.recipe.RecipeList;
0042:        import org.cougaar.tools.csmart.society.SocietyComponent;
0043:        import org.cougaar.tools.csmart.society.ui.SocietyUIComponent;
0044:        import org.cougaar.tools.csmart.ui.util.Util;
0045:        import org.cougaar.util.log.Logger;
0046:
0047:        import javax.swing.*;
0048:        import javax.swing.event.AncestorEvent;
0049:        import javax.swing.event.AncestorListener;
0050:        import javax.swing.event.TreeModelEvent;
0051:        import javax.swing.event.TreeModelListener;
0052:        import javax.swing.event.TreeSelectionEvent;
0053:        import javax.swing.event.TreeSelectionListener;
0054:        import javax.swing.filechooser.FileFilter;
0055:        import javax.swing.tree.DefaultMutableTreeNode;
0056:        import javax.swing.tree.DefaultTreeModel;
0057:        import javax.swing.tree.TreePath;
0058:        import java.awt.*;
0059:        import java.awt.event.ActionEvent;
0060:        import java.awt.event.ActionListener;
0061:        import java.awt.event.MouseEvent;
0062:        import java.io.File;
0063:        import java.io.IOException;
0064:        import java.io.ObjectInputStream;
0065:        import java.util.ArrayList;
0066:        import java.util.Collection;
0067:        import java.util.Collections;
0068:        import java.util.Enumeration;
0069:        import java.util.EventObject;
0070:        import java.util.Map;
0071:        import java.util.Set;
0072:        import java.util.Vector;
0073:
0074:        /**
0075:         * The Organizer holds all the component a user creates
0076:         * and manipulates in CSMART
0077:         * @property org.cougaar.tools.csmart.doWorkspace if false do NOT read / write from the
0078:         * workspace file, nor set listeners to support doing so.
0079:         */
0080:        public class Organizer extends JScrollPane {
0081:            private static final String DEFAULT_FILE_NAME = "Default Workspace.xml";
0082:            private static final String FRAME_TITLE = "CSMART Launcher";
0083:            private static final long UPDATE_DELAY = 5000L;
0084:            private boolean updateNeeded = false;
0085:            private long nextUpdate = 0L;
0086:
0087:            // If you set this give property to false, then no Workspace file is
0088:            // read or written
0089:            private static boolean doWorkspace = true;
0090:            static {
0091:                String s = System
0092:                        .getProperty("org.cougaar.tools.csmart.doWorkspace");
0093:                if ("false".equalsIgnoreCase(s)) {
0094:                    doWorkspace = false;
0095:                }
0096:            }
0097:
0098:            private String workspaceFileName;
0099:            protected CSMART csmart;
0100:            protected DefaultMutableTreeNode root;
0101:            private Object lockObject = new Object();
0102:            protected DefaultTreeModel model;
0103:            protected OrganizerTree workspace;
0104:            private Organizer organizer;
0105:            private CMTDialog cmtDialog;
0106:            private transient Logger log;
0107:
0108:            private DBConflictHandler saveToDbConflictHandler = GUIUtils
0109:                    .createSaveToDbConflictHandler(this );
0110:
0111:            // The stand-alone recipes that can be created in CSMART
0112:            private Object[] recipeNameClassItems = null;
0113:
0114:            // Define Unique Name sets
0115:            private OrganizerNameSet experimentNames = new OrganizerNameSet(
0116:                    "Experiment", "Experiment", "isExperimentNameInDatabase");
0117:            private OrganizerNameSet societyNames = new OrganizerNameSet(
0118:                    "Society", "Society", "isSocietyNameInDatabase");
0119:            private OrganizerNameSet recipeNames = new OrganizerNameSet(
0120:                    "Recipe", "Recipe", "isRecipeNameInDatabase");
0121:            private OrganizerNameSet folderNames = new OrganizerNameSet(
0122:                    "Folder", "Folder", null);
0123:
0124:            // define helper class
0125:            protected OrganizerHelper helper;
0126:
0127:            private ArrayList recipes = new ArrayList();
0128:
0129:            // Define actions for use on menus
0130:
0131:            protected Action newExperimentFromDBAction = new AbstractAction(
0132:                    ActionUtil.NEW_EXPERIMENT_FROM_DB_ACTION) {
0133:                public void actionPerformed(ActionEvent e) {
0134:                    organizer.selectExperimentFromDatabase();
0135:                }
0136:            };
0137:
0138:            protected Action newExperimentFromFileAction = new AbstractAction(
0139:                    ActionUtil.NEW_EXPERIMENT_FROM_FILE_ACTION) {
0140:                public void actionPerformed(ActionEvent e) {
0141:                    organizer.createExperimentFromFile();
0142:                }
0143:            };
0144:
0145:            protected Action newExperimentFromUIAction = new AbstractAction(
0146:                    ActionUtil.NEW_EXPERIMENT_FROM_UI_ACTION) {
0147:                public void actionPerformed(ActionEvent e) {
0148:                    organizer.createExperimentFromUI();
0149:                }
0150:            };
0151:
0152:            protected Action[] newExperimentActions = {
0153:                    newExperimentFromDBAction, newExperimentFromFileAction,
0154:                    newExperimentFromUIAction };
0155:
0156:            protected Action newFolderAction = new AbstractAction(
0157:                    ActionUtil.NEW_FOLDER_ACTION) {
0158:                public void actionPerformed(ActionEvent e) {
0159:                    organizer.newFolder();
0160:                }
0161:            };
0162:
0163:            protected Action renameWorkspaceAction = new AbstractAction(
0164:                    ActionUtil.RENAME_ACTION) {
0165:                public void actionPerformed(ActionEvent e) {
0166:                    organizer.renameWorkspace();
0167:                }
0168:            };
0169:
0170:            protected AbstractAction deleteExperimentFromDatabaseAction = new AbstractAction(
0171:                    ActionUtil.DELETE_EXPERIMENT_FROM_DATABASE_ACTION) {
0172:                public void actionPerformed(ActionEvent e) {
0173:                    organizer.deleteExperimentFromDatabase();
0174:                }
0175:            };
0176:
0177:            protected AbstractAction deleteRecipeFromDatabaseAction = new AbstractAction(
0178:                    ActionUtil.DELETE_RECIPE_FROM_DATABASE_ACTION) {
0179:                public void actionPerformed(ActionEvent e) {
0180:                    organizer.deleteRecipeFromDatabase();
0181:                }
0182:            };
0183:
0184:            protected AbstractAction buildExperimentAction = new AbstractAction(
0185:                    ActionUtil.BUILD_ACTION, new ImageIcon(getClass()
0186:                            .getResource("Experiment16t.gif"))) {
0187:                public void actionPerformed(ActionEvent e) {
0188:                    organizer.startExperimentBuilder();
0189:                }
0190:            };
0191:
0192:            protected AbstractAction runExperimentAction = new AbstractAction(
0193:                    ActionUtil.RUN_ACTION, new ImageIcon(getClass()
0194:                            .getResource("EC16.gif"))) {
0195:                public void actionPerformed(ActionEvent e) {
0196:                    organizer.startConsole();
0197:                }
0198:            };
0199:
0200:            protected AbstractAction duplicateAction = new AbstractAction(
0201:                    ActionUtil.DUPLICATE_ACTION) {
0202:                public void actionPerformed(ActionEvent e) {
0203:                    organizer.duplicate();
0204:                }
0205:            };
0206:
0207:            protected AbstractAction deleteExperimentAction = new AbstractAction(
0208:                    ActionUtil.DELETE_ACTION) {
0209:                public void actionPerformed(ActionEvent e) {
0210:                    organizer.deleteExperiment();
0211:                }
0212:            };
0213:
0214:            protected AbstractAction deleteAction = new AbstractAction(
0215:                    ActionUtil.DELETE_ACTION) {
0216:                public void actionPerformed(ActionEvent e) {
0217:                    organizer.delete();
0218:                }
0219:            };
0220:
0221:            protected AbstractAction renameExperimentAction = new AbstractAction(
0222:                    ActionUtil.RENAME_ACTION) {
0223:                public void actionPerformed(ActionEvent e) {
0224:                    organizer.renameExperiment();
0225:                }
0226:            };
0227:
0228:            protected AbstractAction renameAction = new AbstractAction(
0229:                    ActionUtil.RENAME_ACTION) {
0230:                public void actionPerformed(ActionEvent e) {
0231:                    organizer.rename();
0232:                }
0233:            };
0234:
0235:            protected AbstractAction configureAction = new AbstractAction(
0236:                    ActionUtil.CONFIGURE_ACTION, new ImageIcon(getClass()
0237:                            .getResource("SB16.gif"))) {
0238:                public void actionPerformed(ActionEvent e) {
0239:                    organizer.startBuilder();
0240:                }
0241:            };
0242:
0243:            protected AbstractAction deleteRecipeAction = new AbstractAction(
0244:                    ActionUtil.DELETE_ACTION) {
0245:                public void actionPerformed(ActionEvent e) {
0246:                    organizer.deleteRecipe();
0247:                }
0248:            };
0249:
0250:            protected AbstractAction renameRecipeAction = new AbstractAction(
0251:                    ActionUtil.RENAME_ACTION) {
0252:                public void actionPerformed(ActionEvent e) {
0253:                    organizer.renameRecipe();
0254:                }
0255:            };
0256:
0257:            protected AbstractAction deleteFolderAction = new AbstractAction(
0258:                    ActionUtil.DELETE_ACTION) {
0259:                public void actionPerformed(ActionEvent e) {
0260:                    organizer.deleteFolder();
0261:                }
0262:            };
0263:
0264:            protected AbstractAction renameFolderAction = new AbstractAction(
0265:                    ActionUtil.RENAME_ACTION) {
0266:                public void actionPerformed(ActionEvent e) {
0267:                    organizer.renameFolder();
0268:                }
0269:            };
0270:
0271:            protected AbstractAction deleteSocietyAction = new AbstractAction(
0272:                    ActionUtil.DELETE_ACTION) {
0273:                public void actionPerformed(ActionEvent e) {
0274:                    organizer.deleteSociety();
0275:                }
0276:            };
0277:
0278:            protected AbstractAction renameSocietyAction = new AbstractAction(
0279:                    ActionUtil.RENAME_ACTION) {
0280:                public void actionPerformed(ActionEvent e) {
0281:                    organizer.renameSociety();
0282:                }
0283:            };
0284:
0285:            protected AbstractAction newRecipeFromDatabaseAction = new AbstractAction(
0286:                    "From Database") {
0287:                public void actionPerformed(ActionEvent e) {
0288:                    organizer.selectRecipeFromDatabase();
0289:                }
0290:            };
0291:
0292:            protected AbstractAction newRecipeBuiltInAction = new AbstractAction(
0293:                    "From Template") {
0294:                public void actionPerformed(ActionEvent e) {
0295:                    organizer.newRecipe();
0296:                }
0297:            };
0298:
0299:            protected Action[] newRecipeActions = {
0300:                    newRecipeFromDatabaseAction, newRecipeBuiltInAction };
0301:
0302:            protected AbstractAction saveAction = new AbstractAction("Save") {
0303:                public void actionPerformed(ActionEvent e) {
0304:                    organizer.saveInDatabase();
0305:                }
0306:            };
0307:
0308:            /**
0309:             * Construct a workspace, i.e. an user interface for a tree
0310:             * of components (experiments, societies, recipes).
0311:             * Reads the previous workspace from "Default Workspace.xml"
0312:             * @param csmart The <code>CSMART</code> user interface containing this.
0313:             */
0314:            public Organizer(CSMART csmart) {
0315:                this (csmart, null);
0316:            }
0317:
0318:            /**
0319:             * Construct a workspace, i.e. an user interface for a tree
0320:             * of components (experiments, societies, recipes).
0321:             * If the workspace file name parameter is null,
0322:             * reads the previous workspace from "Default Workspace.xml"
0323:             * @param csmart The <code>CSMART</code> user interface containing this.
0324:             * @param workspaceFileName file from which to read previous workspace
0325:             */
0326:            public Organizer(CSMART csmart, String workspaceFileName) {
0327:                createLogger();
0328:                organizer = this ;
0329:                helper = new OrganizerHelper(this );
0330:                initRecipes();
0331:
0332:                setPreferredSize(new Dimension(400, 400));
0333:                JPanel panel = new JPanel(new BorderLayout());
0334:                setViewportView(panel);
0335:                this .csmart = csmart;
0336:                if (workspaceFileName == null) {
0337:                    this .workspaceFileName = DEFAULT_FILE_NAME;
0338:                } else {
0339:                    this .workspaceFileName = workspaceFileName;
0340:                }
0341:
0342:                restore(this .workspaceFileName);
0343:
0344:                if (!doWorkspace) {
0345:                    if (log.isInfoEnabled()) {
0346:                        log.info("Not using workspace file");
0347:                    }
0348:                }
0349:
0350:                if (root == null) {
0351:                    root = new DefaultMutableTreeNode(null, true);
0352:                    model = new DefaultTreeModel(root);
0353:                }
0354:                model.setAsksAllowsChildren(true);
0355:
0356:                // This listener is only used to call update
0357:                if (doWorkspace)
0358:                    model.addTreeModelListener(myModelListener);
0359:
0360:                // When restoring workspace file, this should have been done already
0361:                if (workspace == null)
0362:                    workspace = new OrganizerTree(model);
0363:
0364:                DefaultCellEditor myEditor = new DefaultCellEditor(
0365:                        new JTextField()) {
0366:                    public boolean isCellEditable(EventObject e) {
0367:                        if (super .isCellEditable(e) && e instanceof  MouseEvent) {
0368:                            TreePath path = workspace.getPathForLocation(
0369:                                    ((MouseEvent) e).getX(), ((MouseEvent) e)
0370:                                            .getY());
0371:                            if (path == null)
0372:                                return false;
0373:                            Object o = path.getLastPathComponent();
0374:                            Object userObject = ((DefaultMutableTreeNode) o)
0375:                                    .getUserObject();
0376:                            if (userObject instanceof  ModifiableComponent) {
0377:                                // don't allow edits which change the name,
0378:                                // use Rename menu action instead
0379:                                return false;
0380:                            } else
0381:                                return true; // renaming workspace or folder is always ok
0382:                        }
0383:                        return false;
0384:                    }
0385:                };
0386:                workspace.setCellEditor(myEditor);
0387:                workspace.setCellRenderer(new OrganizerTreeCellRenderer(this ));
0388:                workspace.setExpandsSelectedPaths(true);
0389:                workspace.addTreeSelectionListener(mySelectionListener);
0390:                workspace.addAncestorListener(myAncestorListener);
0391:                workspace.setSelection(root);
0392:                workspace.addMouseListener(new OrganizerMouseListener(this ,
0393:                        workspace));
0394:                expandTree(); // fully expand workspace tree
0395:                panel.add(workspace);
0396:                setViewportView(panel);
0397:                if (doWorkspace)
0398:                    updater.start();
0399:            }
0400:
0401:            private void createLogger() {
0402:                log = CSMART.createLogger(this .getClass().getName());
0403:            }
0404:
0405:            private void initRecipes() {
0406:                recipeNameClassItems = new Object[RecipeList.getRecipeCount()];
0407:                for (int i = 0; i < RecipeList.getRecipeCount(); i++) {
0408:                    recipeNameClassItems[i] = new NameClassItem(RecipeList
0409:                            .getRecipeName(i), RecipeList.getRecipeClass(i));
0410:                }
0411:            }
0412:
0413:            /**
0414:             * Get the society component with the given name from the workspace;
0415:             * this ensures that there is exactly one object per component
0416:             * in the workspace.
0417:             */
0418:
0419:            public SocietyComponent getSociety(String name) {
0420:                return (SocietyComponent) societyNames.getObjectInTree(
0421:                        SocietyComponent.class, root, name);
0422:            }
0423:
0424:            public RecipeComponent getRecipe(String name) {
0425:                return (RecipeComponent) recipeNames.getObjectInTree(
0426:                        RecipeComponent.class, root, name);
0427:            }
0428:
0429:            ///////////////////////////////////////
0430:            // Methods to get the user's selection
0431:            ///////////////////////////////////////
0432:
0433:            protected DefaultMutableTreeNode getSelectedNode() {
0434:                TreePath selPath = workspace.getSelectionPath();
0435:                if (selPath == null)
0436:                    return null;
0437:                return (DefaultMutableTreeNode) selPath.getLastPathComponent();
0438:            }
0439:
0440:            ////////////////////////////////////
0441:            // Start tools; used to start tools from menus
0442:            ////////////////////////////////////
0443:
0444:            protected void startBuilder() {
0445:                csmart.runBuilder((ModifiableComponent) getSelectedNode()
0446:                        .getUserObject(), false);
0447:            }
0448:
0449:            private DBExperiment createExperiment(SocietyComponent society) {
0450:                String name = generateExperimentName("Experiment for "
0451:                        + society.getSocietyName(), false);
0452:                if (name == null)
0453:                    return null;
0454:                return new DBExperiment(name, society, new RecipeComponent[0]);
0455:            }
0456:
0457:            private DBExperiment createExperiment(RecipeComponent recipe) {
0458:                String name = generateExperimentName("Experiment for "
0459:                        + recipe.getRecipeName(), false);
0460:                if (name == null)
0461:                    return null;
0462:                return new DBExperiment(name, null,
0463:                        new RecipeComponent[] { recipe });
0464:            }
0465:
0466:            /**
0467:             * When called from Organizer, the selected user object is an experiment.
0468:             * When called from CSMART File-Build menu, the
0469:             * selected user object is a recipe or society.
0470:             */
0471:            protected void startExperimentBuilder() {
0472:                DBExperiment experiment = null;
0473:                DefaultMutableTreeNode node = getSelectedNode();
0474:                Object o = node.getUserObject();
0475:                if (o instanceof  SocietyComponent) {
0476:                    experiment = createExperiment((SocietyComponent) o);
0477:                    if (experiment != null)
0478:                        addExperimentAndComponentsToWorkspace(experiment,
0479:                                (DefaultMutableTreeNode) node.getParent());
0480:                } else if (o instanceof  RecipeComponent) {
0481:                    experiment = createExperiment((RecipeComponent) o);
0482:                    if (experiment != null)
0483:                        addExperimentAndComponentsToWorkspace(experiment,
0484:                                (DefaultMutableTreeNode) node.getParent());
0485:                } else if (o instanceof  Experiment)
0486:                    experiment = (DBExperiment) o;
0487:                if (experiment != null)
0488:                    csmart.runExperimentBuilder(experiment, false);
0489:            }
0490:
0491:            /**
0492:             * Try to run the console.  This is called in three cases:
0493:             * 1) the user has selected a runnable experiment
0494:             * 2) the user has selected a society and this method creates an experiment
0495:             * 3) the user has not selected an experiment and plans to attach to running nodes
0496:             */
0497:            protected void startConsole() {
0498:                DefaultMutableTreeNode node = getSelectedNode();
0499:                if (node == null) {
0500:                    csmart.runConsole(null);
0501:                    return;
0502:                }
0503:                Object o = node.getUserObject();
0504:                DBExperiment experiment = null;
0505:                if (o instanceof  SocietyComponent) {
0506:                    experiment = createExperiment((SocietyComponent) o);
0507:                    if (experiment == null)
0508:                        return;
0509:                    addExperimentAndComponentsToWorkspace(experiment,
0510:                            (DefaultMutableTreeNode) node.getParent());
0511:                    if (!experiment.hasConfiguration())
0512:                        experiment.createDefaultConfiguration();
0513:                    // TODO: this generates an error -- null trial id in PdbBase.put
0514:                    experiment.save(saveToDbConflictHandler);
0515:                } else if (o instanceof  Experiment) {
0516:                    experiment = (DBExperiment) o;
0517:                }
0518:                // Start up the console on the experiment or with no experiment
0519:                csmart.runConsole(experiment);
0520:            }
0521:
0522:            ///////////////////////////////////
0523:            // Unique name support
0524:            //////////////////////////////////
0525:
0526:            /**
0527:             * Get a unique name, optionally allowing the existing name.
0528:             * Prompts the user for a name based on the original name,
0529:             * and then checks the user entered value for uniqueness in
0530:             * the CSMART workspace and in the database.
0531:             */
0532:
0533:            public String getUniqueExperimentName(String originalName,
0534:                    boolean allowExistingName) {
0535:                return experimentNames.getUniqueName(originalName,
0536:                        allowExistingName);
0537:            }
0538:
0539:            protected String getUniqueSocietyName(String originalName,
0540:                    boolean allowExistingName) {
0541:                return societyNames.getUniqueName(originalName,
0542:                        allowExistingName);
0543:            }
0544:
0545:            protected String getUniqueRecipeName(String originalName,
0546:                    boolean allowExistingName) {
0547:                return recipeNames.getUniqueName(originalName,
0548:                        allowExistingName);
0549:            }
0550:
0551:            private String getUniqueFolderName(String originalName,
0552:                    boolean allowExistingName) {
0553:                return folderNames.getUniqueName(originalName,
0554:                        allowExistingName);
0555:            }
0556:
0557:            protected boolean isUniqueSocietyName(String name) {
0558:                return societyNames.isUniqueName(name);
0559:            }
0560:
0561:            /**
0562:             * Generate unique names.  Only prompts user if a generated
0563:             * name conflicts in the database.
0564:             */
0565:
0566:            protected String generateExperimentName(String name,
0567:                    boolean allowExistingName) {
0568:                return experimentNames.generateUniqueName(name,
0569:                        allowExistingName);
0570:            }
0571:
0572:            protected String generateSocietyName(String name,
0573:                    boolean allowExistingName) {
0574:                return societyNames.generateUniqueName(name, allowExistingName);
0575:            }
0576:
0577:            protected String generateRecipeName(String name,
0578:                    boolean allowExistingName) {
0579:                return recipeNames.generateUniqueName(name, allowExistingName);
0580:            }
0581:
0582:            /**
0583:             * Generate an unique name with no user input.
0584:             */
0585:
0586:            protected String generateExperimentName(String name) {
0587:                return experimentNames.generateName(name);
0588:            }
0589:
0590:            protected String generateSocietyName(String name) {
0591:                return societyNames.generateName(name);
0592:            }
0593:
0594:            ///////////////////////////////////
0595:            // New Experiments
0596:            //////////////////////////////////
0597:
0598:            protected void createExperimentFromFile() {
0599:                SocietyComponent society = helper.createSocietyFromFile();
0600:                if (society == null)
0601:                    return;
0602:                DBExperiment experiment = createExperiment(society);
0603:
0604:                // Add in community info for this society
0605:                JFileChooser chooser = new JFileChooser(System
0606:                        .getProperty("org.cougaar.install.path"));
0607:                chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
0608:                chooser
0609:                        .setDialogTitle("Select the communities.xml file for this Society, if any");
0610:                // Allow selection of XML files and directories
0611:                chooser.addChoosableFileFilter(new FileFilter() {
0612:                    public boolean accept(File f) {
0613:                        if (f == null)
0614:                            return false;
0615:                        if (f.isDirectory())
0616:                            return true;
0617:                        if (!f.canRead())
0618:                            return false;
0619:                        return f.getName().endsWith(".xml");
0620:                    }
0621:
0622:                    public String getDescription() {
0623:                        return "XML Files";
0624:                    }
0625:
0626:                });
0627:
0628:                File xmlFile = null;
0629:                while (xmlFile == null) {
0630:                    int result = chooser.showDialog(organizer, "OK");
0631:                    if (result != JFileChooser.APPROVE_OPTION)
0632:                        break;
0633:                    xmlFile = chooser.getSelectedFile();
0634:                    if (xmlFile != null) {
0635:                        if (!xmlFile.canRead())
0636:                            xmlFile = null;
0637:                    }
0638:                }
0639:
0640:                if (xmlFile != null
0641:                        && !CommunityDbUtils.importCommunityXML(xmlFile,
0642:                                experiment.getCommAsbID())) {
0643:                    // There may have been none, so don't complain too loudly.
0644:                    if (log.isInfoEnabled()) {
0645:                        log
0646:                                .info("crtExpFromFile got no Community XML data out of "
0647:                                        + xmlFile.getAbsolutePath());
0648:                    }
0649:                } else if (log.isDebugEnabled()) {
0650:                    log.debug("crtExpFromFile had xmlFile: " + xmlFile
0651:                            + " and or return from CommDbUtils not false");
0652:                }
0653:
0654:                DefaultMutableTreeNode experimentNode = addExperimentToWorkspace(
0655:                        experiment, getSelectedNode());
0656:                addSocietyToWorkspace(society, experimentNode);
0657:            }
0658:
0659:            /**
0660:             * Create an experiment and a society that will be specified
0661:             * from the user interface.
0662:             */
0663:            protected void createExperimentFromUI() {
0664:                String name = getUniqueExperimentName("", false);
0665:                if (name == null)
0666:                    return;
0667:                SocietyComponent society = new SocietyUIComponent(
0668:                        "Society for " + name);
0669:                DBExperiment experiment = new DBExperiment(name, society, null);
0670:                DefaultMutableTreeNode experimentNode = addExperimentToWorkspace(
0671:                        experiment, getSelectedNode());
0672:                addSocietyToWorkspace(society, experimentNode);
0673:            }
0674:
0675:            ///////////////////////////////////
0676:            // New Societies
0677:            //////////////////////////////////
0678:
0679:            protected void addSociety(SocietyComponent sc) {
0680:                // add society as sibling of experiment
0681:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) (getSelectedNode()
0682:                        .getParent());
0683:                addSocietyToWorkspace(sc, parentNode);
0684:            }
0685:
0686:            /////////////////////////////////
0687:            // New Recipes
0688:            /////////////////////////////////
0689:
0690:            /**
0691:             * Ensure that recipe name is unique in both CSMART and the database.
0692:             * Optionally allow re-use of existing name.
0693:             */
0694:            protected void newRecipe() {
0695:                Object[] values = recipeNameClassItems;
0696:                Object answer = JOptionPane.showInputDialog(this ,
0697:                        "Select Recipe Type", "Select Recipe",
0698:                        JOptionPane.QUESTION_MESSAGE, null, values,
0699:                        "Empty Recipe");
0700:                if (answer instanceof  NameClassItem) {
0701:                    NameClassItem item = (NameClassItem) answer;
0702:                    //      String name = generateRecipeName(item.name, false);
0703:                    String name = recipeNames.getUniqueName(item.name, false);
0704:                    if (name == null)
0705:                        return;
0706:                    RecipeComponent recipe = helper
0707:                            .createRecipe(name, item.cls);
0708:                    if (recipe != null) {
0709:                        recipe.saveToDatabase();
0710:                        addRecipeToWorkspace(recipe, getSelectedNode());
0711:                    }
0712:                }
0713:            } // end of newRecipe
0714:
0715:            protected void newFolder() {
0716:                String name = getUniqueFolderName("", false);
0717:                if (name == null)
0718:                    return;
0719:                addFolderToWorkspace(name, getSelectedNode());
0720:            }
0721:
0722:            /////////////////////////////////////
0723:            // Rename items
0724:            /////////////////////////////////////
0725:
0726:            /**
0727:             * Rename a folder, experiment, society or recipe.
0728:             */
0729:            protected void rename() {
0730:                DefaultMutableTreeNode node = getSelectedNode();
0731:                if (node == null)
0732:                    return;
0733:                Object o = node.getUserObject();
0734:                if (o == null)
0735:                    return;
0736:                if (node.isRoot())
0737:                    renameWorkspace();
0738:                else if (o instanceof  Experiment)
0739:                    renameExperiment();
0740:                else if (o instanceof  SocietyComponent)
0741:                    renameSociety();
0742:                else if (o instanceof  RecipeComponent)
0743:                    renameRecipe();
0744:                else if (o instanceof  String)
0745:                    renameFolder();
0746:            }
0747:
0748:            /**
0749:             * Rename the top-level workspace.
0750:             */
0751:
0752:            protected void renameWorkspace() {
0753:                String name = JOptionPane.showInputDialog("New workspace name");
0754:                if (name == null || name.equals(""))
0755:                    return;
0756:                workspaceFileName = name;
0757:                String rootName = this .workspaceFileName;
0758:                int extpos = this .workspaceFileName.lastIndexOf('.');
0759:                if (extpos >= 0) {
0760:                    rootName = rootName.substring(0, extpos);
0761:                }
0762:                root.setUserObject(rootName);
0763:                model.nodeChanged(root);
0764:                if (doWorkspace)
0765:                    update();
0766:            }
0767:
0768:            /**
0769:             * Rename an experiment.
0770:             */
0771:
0772:            protected void renameExperiment() {
0773:                DefaultMutableTreeNode node = getSelectedNode();
0774:                final DBExperiment experiment = (DBExperiment) node
0775:                        .getUserObject();
0776:                String originalName = experiment.getExperimentName();
0777:                String newName = getUniqueExperimentName(originalName, true);
0778:                if (newName == null)
0779:                    return;
0780:                if (newName.equals(originalName))
0781:                    return;
0782:                experimentNames.remove(originalName);
0783:                experiment.setName(newName);
0784:                if (experiment.isModified()) {
0785:                    GUIUtils.timeConsumingTaskStart(organizer);
0786:                    try {
0787:                        new Thread("SaveExperiment") {
0788:                            public void run() {
0789:                                experiment.save(saveToDbConflictHandler); // save under new name
0790:                                GUIUtils.timeConsumingTaskEnd(organizer);
0791:                            }
0792:                        }.start();
0793:                    } catch (RuntimeException re) {
0794:                        if (log.isErrorEnabled()) {
0795:                            log
0796:                                    .error(
0797:                                            "Runtime exception saving experiment",
0798:                                            re);
0799:                        }
0800:                        GUIUtils.timeConsumingTaskEnd(organizer);
0801:                    }
0802:                } // end of block to see if expt was modified.
0803:                experimentNames.add(newName);
0804:                model.nodeChanged(node);
0805:            }
0806:
0807:            /**
0808:             * Rename a society.
0809:             * If the society is in an experiment,
0810:             * copy the society, rename it, and  save it to the database.
0811:             * If it's not in an experiment, then warn the user that they
0812:             * need to save any experiments that contain it.
0813:             */
0814:            protected void renameSociety() {
0815:                DefaultMutableTreeNode node = getSelectedNode();
0816:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node
0817:                        .getParent();
0818:                //    int index = parentNode.getIndex(node);
0819:                SocietyComponent society = (SocietyComponent) node
0820:                        .getUserObject();
0821:                String originalName = society.getSocietyName();
0822:                String newName = getUniqueSocietyName(originalName, true);
0823:                if (newName == null)
0824:                    return;
0825:                if (newName.equals(originalName))
0826:                    return;
0827:                societyNames.remove(originalName);
0828:                Object o = parentNode.getUserObject();
0829:                if (o instanceof  Experiment) {
0830:                    Experiment experiment = (Experiment) o;
0831:                    model.removeNodeFromParent(node);
0832:                    experiment.removeSocietyComponent();
0833:                    SocietyComponent societyCopy = (SocietyComponent) society
0834:                            .copyAndSave(newName);
0835:                    experiment.addSocietyComponent(societyCopy);
0836:
0837:                    addSocietyToWorkspace(societyCopy, parentNode);
0838:                } else {
0839:                    societyNames.add(newName);
0840:                    // Make this method in SocietyBase do the DB update
0841:                    // so we dont have to do a separate save
0842:                    society.setName(newName);
0843:                    //society.saveToDatabase();
0844:                    Enumeration nodes = root.depthFirstEnumeration();
0845:                    while (nodes.hasMoreElements()) {
0846:                        node = (DefaultMutableTreeNode) nodes.nextElement();
0847:                        if (node.getUserObject().equals(society))
0848:                            model.nodeChanged(node);
0849:                    }
0850:                    displayExperiments(society);
0851:                }
0852:            }
0853:
0854:            /**
0855:             * Rename a recipe.
0856:             * If the recipe is in an experiment,
0857:             * copy the recipe, rename it, and  save it to the database.
0858:             * If it's not in an experiment, then warn the user that they
0859:             * need to save any experiments that contain it.
0860:             */
0861:            protected void renameRecipe() {
0862:                DefaultMutableTreeNode node = getSelectedNode();
0863:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node
0864:                        .getParent();
0865:                //    int index = parentNode.getIndex(node);
0866:                final RecipeComponent recipe = (RecipeComponent) node
0867:                        .getUserObject();
0868:                String originalName = recipe.getRecipeName();
0869:                String newName = getUniqueRecipeName(originalName, true);
0870:                if (newName == null)
0871:                    return;
0872:                if (newName.equals(originalName))
0873:                    return;
0874:
0875:                Object o = parentNode.getUserObject();
0876:
0877:                // If its local, create a copy with the new name
0878:                if (o instanceof  Experiment) {
0879:                    Experiment experiment = (Experiment) o;
0880:                    model.removeNodeFromParent(node);
0881:                    experiment.removeRecipeComponent(recipe);
0882:                    RecipeComponent recipeCopy = (RecipeComponent) recipe
0883:                            .copy(newName);
0884:                    experiment.addRecipeComponent(recipeCopy);
0885:                    recipeCopy.saveToDatabase();
0886:                    addRecipeToWorkspace(recipeCopy, parentNode);
0887:
0888:                    // If there are no other Nodes in the model with the originalName
0889:                    // then and only then we want to remove that name from the list
0890:                    // of recipeNames
0891:                    boolean nameStillUsed = false;
0892:                    Enumeration nodes = root.depthFirstEnumeration();
0893:                    while (nodes.hasMoreElements()) {
0894:                        node = (DefaultMutableTreeNode) nodes.nextElement();
0895:                        if (node.getUserObject().equals(recipe)) {
0896:                            // Original recipe still in the model someplace
0897:                            // so don't remove the name
0898:                            nameStillUsed = true;
0899:                            break;
0900:                        }
0901:                    }
0902:                    if (!nameStillUsed)
0903:                        recipeNames.remove(originalName);
0904:                } else {
0905:                    // Only really want to remove
0906:                    // the original name if there are no other nodes with this name
0907:                    // If its global (as in this block) we're going to change
0908:                    // the recipe name throughout so this is correct
0909:                    recipeNames.remove(originalName);
0910:
0911:                    recipeNames.add(newName);
0912:
0913:                    // This method now updates the DB as well
0914:                    recipe.setName(newName);
0915:
0916:                    // So only save it to the DB if necessary
0917:                    // Note however that
0918:                    // since the property names may have changed,
0919:                    // it may be I always want to re-save
0920:                    if (recipe.isModified())
0921:                        recipe.saveToDatabase();
0922:
0923:                    Enumeration nodes = root.depthFirstEnumeration();
0924:                    while (nodes.hasMoreElements()) {
0925:                        node = (DefaultMutableTreeNode) nodes.nextElement();
0926:                        if (node.getUserObject().equals(recipe))
0927:                            model.nodeChanged(node);
0928:                    }
0929:
0930:                    // Now that changing a recipe name
0931:                    // doesn't change the recipe ID, there is no need to
0932:                    // resave all these experiments
0933:                    // when you change a recipe name
0934:                    //      displayExperiments(recipe);
0935:                } // end of block on global change
0936:            }
0937:
0938:            /**
0939:             * Rename a folder.
0940:             */
0941:
0942:            protected void renameFolder() {
0943:                String originalName = (String) (getSelectedNode()
0944:                        .getUserObject());
0945:                String newName = getUniqueFolderName(originalName, true);
0946:                if (newName == null)
0947:                    return;
0948:                DefaultMutableTreeNode node = getSelectedNode();
0949:                if (node.getUserObject().equals(newName))
0950:                    return;
0951:                node.setUserObject(newName);
0952:                model.nodeChanged(node);
0953:                folderNames.remove(originalName);
0954:                folderNames.add(newName);
0955:            }
0956:
0957:            ///////////////////////////////////
0958:            // Select items from database
0959:            ///////////////////////////////////
0960:
0961:            /**
0962:             * Prompt the user for an experiment to load from the database.
0963:             * Return an array with 2 string: experiment name and ID.
0964:             * Note that the return is null if the user cancels the operation in any way.
0965:             **/
0966:            protected String[] selectExperimentFromDBToLoad() {
0967:                Map experimentNamesMap = ExperimentDB.getExperimentNames();
0968:                Set keys = experimentNamesMap.keySet();
0969:                JComboBox cb = new JComboBox(keys.toArray(new String[keys
0970:                        .size()]));
0971:                cb.setEditable(false);
0972:                JPanel panel = new JPanel();
0973:                panel.add(new JLabel("Select Experiment:"));
0974:                panel.add(cb);
0975:                int result = JOptionPane.showConfirmDialog(null, panel,
0976:                        "Experiment", JOptionPane.OK_CANCEL_OPTION,
0977:                        JOptionPane.PLAIN_MESSAGE);
0978:                if (result != JOptionPane.OK_OPTION)
0979:                    return null;
0980:                String experimentName = (String) cb.getSelectedItem();
0981:                // if the CSMART workspace contains an experiment with this name,
0982:                // then force the user to select a new unique name
0983:                if (experimentNames.contains(experimentName)) {
0984:                    experimentName = generateExperimentName(experimentName,
0985:                            false);
0986:                    if (experimentName == null)
0987:                        return null;
0988:                }
0989:
0990:                String[] res = new String[2];
0991:                res[0] = experimentName;
0992:                res[1] = (String) experimentNamesMap.get(experimentName);
0993:                return res;
0994:            }
0995:
0996:            /**
0997:             * Prompt the user for an experiment to load, then create it from the database,
0998:             * and put it in the workspace.
0999:             **/
1000:            protected void selectExperimentFromDatabase() {
1001:                String[] res = selectExperimentFromDBToLoad();
1002:                if (res == null)
1003:                    return;
1004:                selectGivenExperimentFromDatabase(res[0], res[1]);
1005:            }
1006:
1007:            /**
1008:             * Take the given experiment name and ID, and use them to try to load
1009:             * an experiment from the database and add them to the workspace.
1010:             **/
1011:            protected void selectGivenExperimentFromDatabase(
1012:                    String experimentName, String experimentId) {
1013:                selectGivenExperimentFromDatabase(experimentName, experimentId,
1014:                        true);
1015:            }
1016:
1017:            /**
1018:             * Take the given experiment name and ID, and use them to try to load
1019:             * an experiment from the database and add them to the workspace.
1020:             * However, the final argument indicates whether to actually display
1021:             * the CMTDialog window. If not, then whatever threads were already
1022:             * selected will be used to load the experiment.
1023:             **/
1024:            protected void selectGivenExperimentFromDatabase(
1025:                    String experimentName, String experimentId,
1026:                    boolean withPrompt) {
1027:                boolean haveCMTAssembly = false;
1028:                final String originalExperimentName = experimentName;
1029:                // Does this experiment use a CMT assembly for configuration?
1030:                // If so, use the CMTDialog
1031:                // Otherwise, just do the load (which is now done through the CMTDialog)
1032:                // Note: CMTDialog creates a CMTSociety -- should it be creating
1033:                // a SocietyDBComponent?
1034:
1035:                if (log.isDebugEnabled()) {
1036:                    log.debug("selectExperimentFromDB: Experiment Id: "
1037:                            + experimentId + " name: " + originalExperimentName
1038:                            + " will now get name " + experimentName);
1039:                }
1040:
1041:                // Does the experiment have a CMT configuration assembly
1042:                if (DBUtils.containsCMTAssembly(experimentId)) {
1043:                    haveCMTAssembly = true;
1044:                    // get threads and groups information
1045:                    cmtDialog = new CMTDialog(csmart, this , experimentName,
1046:                            experimentId, !withPrompt);
1047:                    while (!cmtDialog.isULThreadSelected()
1048:                            && !cmtDialog.wasCancelled()) {
1049:                        JOptionPane
1050:                                .showMessageDialog(this ,
1051:                                        "You must select at least one thread.",
1052:                                        "No Thread Selected",
1053:                                        JOptionPane.ERROR_MESSAGE);
1054:                        cmtDialog = new CMTDialog(csmart, this , experimentName,
1055:                                experimentId);
1056:                    }
1057:                    if (cmtDialog.wasCancelled())
1058:                        return;
1059:                }
1060:
1061:                if (haveCMTAssembly) {
1062:                    if (log.isDebugEnabled()) {
1063:                        log
1064:                                .debug("selectExptFromDB about to do cmtDialog.processResults");
1065:                    }
1066:                    GUIUtils.timeConsumingTaskStart(organizer);
1067:                    try {
1068:                        new Thread("SelectExperiment") {
1069:                            public void run() {
1070:                                // a potentially long process
1071:                                if (cmtDialog.processResults()) {
1072:                                    final String trialId = cmtDialog
1073:                                            .getTrialId();
1074:                                    if (log.isDebugEnabled()) {
1075:                                        log
1076:                                                .debug("selectExptFromDB after cmtDialog.processResults with new name/id: "
1077:                                                        + cmtDialog
1078:                                                                .getExperimentName()
1079:                                                        + "/"
1080:                                                        + cmtDialog
1081:                                                                .getExperimentId()
1082:                                                        + " trialID: "
1083:                                                        + trialId
1084:                                                        + " and orig name: "
1085:                                                        + originalExperimentName);
1086:                                    }
1087:                                    if (trialId != null) {
1088:                                        DBExperiment experiment = helper
1089:                                                .createExperiment(
1090:                                                        originalExperimentName,
1091:                                                        cmtDialog
1092:                                                                .getExperimentName(),
1093:                                                        cmtDialog
1094:                                                                .getExperimentId(),
1095:                                                        trialId);
1096:                                        if (experiment != null)
1097:                                            addExperimentAndComponentsToWorkspace(
1098:                                                    experiment,
1099:                                                    getSelectedNode());
1100:                                    }
1101:                                }
1102:
1103:                                GUIUtils.timeConsumingTaskEnd(organizer);
1104:                            }
1105:                        }.start();
1106:                    } catch (RuntimeException re) {
1107:                        if (log.isErrorEnabled()) {
1108:                            log.error("Runtime exception creating experiment",
1109:                                    re);
1110:                        }
1111:                        GUIUtils.timeConsumingTaskEnd(organizer);
1112:                    }
1113:                } else {
1114:                    final String trialId = ExperimentDB
1115:                            .getTrialId(experimentId);
1116:                    final String expName = experimentName;
1117:                    final String expId = experimentId;
1118:                    if (log.isDebugEnabled()) {
1119:                        log
1120:                                .debug("selectExptFromDB got nonCMT expt to load. About to call helper to do load with origName: "
1121:                                        + originalExperimentName
1122:                                        + ", new name: "
1123:                                        + expName
1124:                                        + ", new ID: "
1125:                                        + expId
1126:                                        + ", and trialID: " + trialId);
1127:                    }
1128:                    if (trialId != null) {
1129:                        GUIUtils.timeConsumingTaskStart(organizer);
1130:                        try {
1131:                            new Thread("SelectExperiment") {
1132:                                public void run() {
1133:                                    // a potentially long process
1134:                                    DBExperiment experiment = helper
1135:                                            .createExperiment(
1136:                                                    originalExperimentName,
1137:                                                    expName, expId, trialId);
1138:                                    if (experiment != null)
1139:                                        addExperimentAndComponentsToWorkspace(
1140:                                                experiment, getSelectedNode());
1141:                                    GUIUtils.timeConsumingTaskEnd(organizer);
1142:                                }
1143:                            }.start();
1144:                        } catch (RuntimeException re) {
1145:                            if (log.isErrorEnabled()) {
1146:                                log
1147:                                        .error(
1148:                                                "Runtime exception creating experiment",
1149:                                                re);
1150:                            }
1151:                            GUIUtils.timeConsumingTaskEnd(organizer);
1152:                        }
1153:                    } // end of if block
1154:                } // end of else block
1155:            } // end of selectExpFromDB
1156:
1157:            // return true if component is in workspace
1158:            // and is not the child of an experiment
1159:            protected boolean isInWorkspace(ModifiableComponent mc) {
1160:                Enumeration nodes = root.depthFirstEnumeration();
1161:                while (nodes.hasMoreElements()) {
1162:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
1163:                            .nextElement();
1164:                    if (node.getUserObject().equals(mc)) {
1165:                        DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node
1166:                                .getParent();
1167:                        Object parentObject = parentNode.getUserObject();
1168:                        if (parentObject != null
1169:                                && !(parentObject instanceof  Experiment))
1170:                            return true;
1171:                    }
1172:                }
1173:                return false;
1174:            }
1175:
1176:            // TODO: determine how to handle naming of components that
1177:            // are children of the experiment and also at the "top level"
1178:            // these names are currently added twice and not deleted
1179:            // when the experiment is deleted
1180:            protected void addExperimentAndComponentsToWorkspace(
1181:                    DBExperiment experiment, DefaultMutableTreeNode node) {
1182:                DefaultMutableTreeNode expNode = addExperimentToWorkspace(
1183:                        experiment, node);
1184:                SocietyComponent societyComponent = experiment
1185:                        .getSocietyComponent();
1186:
1187:                if (!isInWorkspace(societyComponent))
1188:                    addSocietyToWorkspace(societyComponent, node);
1189:                RecipeComponent[] recipes = experiment.getRecipeComponents();
1190:                for (int i = 0; i < recipes.length; i++)
1191:                    if (!isInWorkspace(recipes[i]))
1192:                        addRecipeToWorkspace(recipes[i], node);
1193:                // add non-editable societies and recipes
1194:                // as children of experiment
1195:                addSocietyToWorkspace(societyComponent, expNode);
1196:                for (int i = 0; i < recipes.length; i++)
1197:                    addRecipeToWorkspace(recipes[i], expNode);
1198:                // select new experiment in workspace
1199:                workspace.setSelection(expNode);
1200:            }
1201:
1202:            protected void selectRecipeFromDatabase() {
1203:                Map recipeNamesHT = helper.getRecipeNamesFromDatabase();
1204:                Set dbRecipeNames = recipeNamesHT.keySet();
1205:                if (dbRecipeNames.isEmpty()) {
1206:                    JOptionPane.showMessageDialog(this ,
1207:                            "There are no recipes in the database",
1208:                            "No Database Recipes",
1209:                            JOptionPane.INFORMATION_MESSAGE);
1210:                    return;
1211:                }
1212:                Object[] selectedRecipes = Util.getObjectsFromList(this ,
1213:                        new ArrayList(dbRecipeNames), "Recipes",
1214:                        "Select Recipes");
1215:                if (selectedRecipes == null)
1216:                    return;
1217:                // where to put the new recipes
1218:                DefaultMutableTreeNode parentNode = getSelectedNode();
1219:                if (parentNode == null)
1220:                    parentNode = root;
1221:                for (int i = 0; i < selectedRecipes.length; i++) {
1222:                    String recipeName = (String) selectedRecipes[i];
1223:                    String recipeId = (String) recipeNamesHT.get(recipeName);
1224:                    if (recipeNames.contains(recipeName))
1225:                        recipeName = recipeNames.getUniqueName(recipeName,
1226:                                false);
1227:                    if (recipeName == null)
1228:                        return;
1229:                    RecipeComponent rc = helper.getDatabaseRecipe(recipeId,
1230:                            recipeName);
1231:                    if (rc != null)
1232:                        addRecipeToWorkspace(rc, parentNode);
1233:                }
1234:            }
1235:
1236:            ////////////////////////////////////
1237:            // Copy items
1238:            ////////////////////////////////////
1239:
1240:            /**
1241:             * Copy an experiment, society or recipe.
1242:             */
1243:
1244:            protected void duplicate() {
1245:                DefaultMutableTreeNode node = getSelectedNode();
1246:                if (node == null)
1247:                    return;
1248:                Object o = node.getUserObject();
1249:                if (o == null)
1250:                    return;
1251:                if (o instanceof  Experiment)
1252:                    copyExperiment((Experiment) o, true);
1253:                else if (o instanceof  SocietyComponent)
1254:                    copySociety((SocietyComponent) o);
1255:                else if (o instanceof  RecipeComponent)
1256:                    copyRecipe((RecipeComponent) o);
1257:            }
1258:
1259:            protected Experiment copyExperiment(Experiment experiment,
1260:                    boolean save) {
1261:                String newName = generateExperimentName(experiment
1262:                        .getExperimentName(), false);
1263:                if (newName == null)
1264:                    return null;
1265:                final DBExperiment experimentCopy = (DBExperiment) experiment
1266:                        .copy(newName);
1267:                if (save) {
1268:                    // save copy in database
1269:                    GUIUtils.timeConsumingTaskStart(organizer);
1270:                    try {
1271:                        new Thread("DuplicateExperiment") {
1272:                            public void run() {
1273:                                experimentCopy.save(saveToDbConflictHandler);
1274:                                GUIUtils.timeConsumingTaskEnd(organizer);
1275:                            }
1276:                        }.start();
1277:                    } catch (RuntimeException re) {
1278:                        if (log.isErrorEnabled()) {
1279:                            log.error(
1280:                                    "Runtime exception duplicating experiment",
1281:                                    re);
1282:                        }
1283:                        GUIUtils.timeConsumingTaskEnd(organizer);
1284:                    }
1285:                }
1286:                DefaultMutableTreeNode node = (DefaultMutableTreeNode) findNode(
1287:                        experiment).getParent();
1288:                if (node == null) {
1289:                    if (log.isErrorEnabled()) {
1290:                        log.error("Experiment not found in workspace: "
1291:                                + experiment.getExperimentName());
1292:                    }
1293:                }
1294:                // add copy as sibling of original
1295:                addExperimentAndComponentsToWorkspace(experimentCopy, node);
1296:                return experimentCopy;
1297:            }
1298:
1299:            /**
1300:             * Copy society; save the society to the database;
1301:             * put the society in the workspace.
1302:             * If the society is in an experiment, put the society in the workspace
1303:             * as a sibling of the experiment, else put it in the workspace
1304:             * as a sibling of the society.
1305:             * @param society the society to copy
1306:             * @return SocietyComponent the copied society
1307:             */
1308:            protected SocietyComponent copySociety(SocietyComponent society) {
1309:                String newName = generateSocietyName(society.getSocietyName(),
1310:                        false);
1311:                if (newName == null)
1312:                    return null;
1313:                final SocietyComponent societyCopy = (SocietyComponent) society
1314:                        .copy(newName);
1315:                // save society copy
1316:                GUIUtils.timeConsumingTaskStart(organizer);
1317:                try {
1318:                    new Thread("DuplicateSociety") {
1319:                        public void run() {
1320:                            // Check the return value?
1321:                            societyCopy.saveToDatabase();
1322:                            GUIUtils.timeConsumingTaskEnd(organizer);
1323:                        }
1324:                    }.start();
1325:                } catch (RuntimeException re) {
1326:                    if (log.isErrorEnabled()) {
1327:                        log.error("Runtime exception duplicating society", re);
1328:                    }
1329:                    GUIUtils.timeConsumingTaskEnd(organizer);
1330:                }
1331:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) getSelectedNode()
1332:                        .getParent();
1333:                if (isSelectedNodeInExperiment())
1334:                    addSocietyToWorkspace(societyCopy,
1335:                            (DefaultMutableTreeNode) parentNode.getParent());
1336:                else
1337:                    addSocietyToWorkspace(societyCopy, parentNode);
1338:                return societyCopy;
1339:            }
1340:
1341:            /**
1342:             * Copy the recipe component; generate a new unique name for the copy;
1343:             * add the copy to the Workspace as a sibling of the original.
1344:             * If the recipe is in an experiment, put the recipe in the workspace
1345:             * as a sibling of the experiment, else put it in the workspace
1346:             * as a sibling of the recipe.
1347:             * @param recipe the recipe to copy
1348:             * @return RecipeComponent the copied recipe
1349:             */
1350:            protected RecipeComponent copyRecipe(RecipeComponent recipe) {
1351:                String newName = generateRecipeName(recipe.getRecipeName(),
1352:                        false);
1353:                if (newName == null)
1354:                    return null;
1355:                final RecipeComponent recipeCopy = (RecipeComponent) recipe
1356:                        .copy(newName);
1357:
1358:                // If we got an error copying the recipe, don't try to save it
1359:                if (recipeCopy == null)
1360:                    return null;
1361:
1362:                GUIUtils.timeConsumingTaskStart(organizer);
1363:                try {
1364:                    new Thread("DuplicateRecipe") {
1365:                        public void run() {
1366:                            recipeCopy.saveToDatabase();
1367:                            GUIUtils.timeConsumingTaskEnd(organizer);
1368:                        }
1369:                    }.start();
1370:                } catch (RuntimeException re) {
1371:                    if (log.isErrorEnabled()) {
1372:                        log.error("Runtime exception duplicating recipe", re);
1373:                    }
1374:                    GUIUtils.timeConsumingTaskEnd(organizer);
1375:                }
1376:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) getSelectedNode()
1377:                        .getParent();
1378:                if (isSelectedNodeInExperiment())
1379:                    addRecipeToWorkspace(recipeCopy,
1380:                            (DefaultMutableTreeNode) parentNode.getParent());
1381:                else
1382:                    addRecipeToWorkspace(recipeCopy, parentNode);
1383:                return recipeCopy;
1384:            }
1385:
1386:            ////////////////////////////////////
1387:            // Delete items
1388:            ////////////////////////////////////
1389:
1390:            protected void delete() {
1391:                DefaultMutableTreeNode node = getSelectedNode();
1392:                if (node == null)
1393:                    return;
1394:                Object o = node.getUserObject();
1395:                if (o == null)
1396:                    return;
1397:                if (o instanceof  Experiment)
1398:                    deleteExperiment();
1399:                else if (o instanceof  SocietyComponent)
1400:                    deleteSociety();
1401:                else if (o instanceof  RecipeComponent)
1402:                    deleteRecipe();
1403:            }
1404:
1405:            protected void deleteExperiment() {
1406:                deleteExperimentInNode(getSelectedNode());
1407:            }
1408:
1409:            protected void deleteExperimentInNode(DefaultMutableTreeNode node) {
1410:                if (node == null)
1411:                    return;
1412:                DBExperiment experiment = (DBExperiment) node.getUserObject();
1413:                if (!experiment.isEditable()) {
1414:                    int result = JOptionPane.showConfirmDialog(this ,
1415:                            "Experiment " + experiment.getExperimentName()
1416:                                    + " is not editable; delete anyway?",
1417:                            "Experiment Not Editable",
1418:                            JOptionPane.YES_NO_OPTION,
1419:                            JOptionPane.WARNING_MESSAGE);
1420:                    if (result != JOptionPane.YES_OPTION)
1421:                        return;
1422:                }
1423:                model.removeNodeFromParent(node);
1424:                String experimentName = experiment.getExperimentName();
1425:                experimentNames.remove(experimentName);
1426:                SocietyComponent society = experiment.getSocietyComponent();
1427:                if (society != null)
1428:                    societyNames.remove(society.getSocietyName());
1429:                int n = experiment.getRecipeComponentCount();
1430:                for (int i = 0; i < n; i++)
1431:                    recipeNames.remove(experiment.getRecipeComponent(i)
1432:                            .getRecipeName());
1433:                // ask if experiment should be deleted from database
1434:                int result = JOptionPane.showConfirmDialog(this ,
1435:                        "Delete experiment " + experiment.getExperimentName()
1436:                                + " from database?",
1437:                        "Delete Experiment From Database",
1438:                        JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
1439:                if (result != JOptionPane.YES_OPTION)
1440:                    return;
1441:                ExperimentDB.deleteExperiment(experiment.getExperimentID(),
1442:                        experimentName);
1443:            }
1444:
1445:            /**
1446:             * Note that this simply deletes the society from the workspace;
1447:             * if the society was included in an experiment, then the experiment
1448:             * still retains the society.
1449:             */
1450:            protected void deleteSociety() {
1451:                deleteSocietyInNode(getSelectedNode());
1452:            }
1453:
1454:            protected void deleteSocietyInNode(
1455:                    DefaultMutableTreeNode societyNode) {
1456:                SocietyComponent society = (SocietyComponent) societyNode
1457:                        .getUserObject();
1458:                model.removeNodeFromParent(societyNode);
1459:                // if deleted last reference to society in the workspace
1460:                // ask if society should be deleted from database and delete it
1461:                if (findNodeNamed(society.getSocietyName()) != null)
1462:                    return;
1463:                //    removeSocietyFromList(society);
1464:                int answer = JOptionPane.showConfirmDialog(this ,
1465:                        "Delete society " + society.getSocietyName()
1466:                                + " from database?", "Delete Society",
1467:                        JOptionPane.YES_NO_OPTION);
1468:                if (answer == JOptionPane.YES_OPTION) {
1469:                    try {
1470:                        // Will only actually do the delete
1471:                        // if no-one uses it
1472:                        PopulateDb.deleteSociety(society.getAssemblyId());
1473:                    } catch (Exception e) {
1474:                        if (log.isErrorEnabled()) {
1475:                            log.error("Exception deleting society "
1476:                                    + society.getSocietyName() + " from db", e);
1477:                        }
1478:                    }
1479:                }
1480:            }
1481:
1482:            protected void deleteRecipe() {
1483:                deleteRecipeInNode(getSelectedNode());
1484:            }
1485:
1486:            /**
1487:             * Ask user if recipe should be deleted everywhere;
1488:             * if deleting everywhere, remove recipe from all experiments
1489:             * in workspace and warn user to re-save them,
1490:             * then ask user if recipe should be deleted from
1491:             * the database.
1492:             */
1493:            private void deleteRecipeInNode(DefaultMutableTreeNode recipeNode) {
1494:                RecipeComponent recipe = (RecipeComponent) recipeNode
1495:                        .getUserObject();
1496:                model.removeNodeFromParent(recipeNode);
1497:
1498:                // if deleted last reference to recipe in the workspace
1499:                // ask if recipe should be deleted from database and delete it
1500:                if (findNodeNamed(recipe.getRecipeName()) != null)
1501:                    return;
1502:                try {
1503:                    PDbBase pdb = new PDbBase();
1504:                    try {
1505:                        int status = pdb.recipeExists(recipe);
1506:                        if (status == PDbBase.RECIPE_STATUS_EXISTS
1507:                                || status == PDbBase.RECIPE_STATUS_DIFFERS) {
1508:                            int answer = JOptionPane.showConfirmDialog(this ,
1509:                                    "Delete recipe " + recipe.getRecipeName()
1510:                                            + " from database?",
1511:                                    "Delete Recipe", JOptionPane.YES_NO_OPTION);
1512:                            if (answer == JOptionPane.YES_OPTION) {
1513:                                // Even if the user wanted it removed, only remove
1514:                                // it if it is not in use, including any experiments
1515:                                // currently in the workspace
1516:                                // Bug 2032 -- not completely deleting complex recipes
1517:                                if (!pdb.isRecipeUsed(recipe))
1518:                                    helper.deleteRecipe(recipe.getRecipeName());
1519:                                // 	      pdb.removeLibRecipe(recipe);
1520:                            }
1521:                        }
1522:                    } finally {
1523:                        if (pdb != null)
1524:                            pdb.close();
1525:                    }
1526:                } catch (Exception e) {
1527:                    JOptionPane
1528:                            .showMessageDialog(
1529:                                    this ,
1530:                                    "An exception occurred deleting the recipe from the database",
1531:                                    "Error Writing Database",
1532:                                    JOptionPane.ERROR_MESSAGE);
1533:                    if (log.isErrorEnabled()) {
1534:                        log.error("Error removing recipe from DB", e);
1535:                    }
1536:                }
1537:                recipeNames.remove(recipe.getRecipeName());
1538:            }
1539:
1540:            /**
1541:             * Delete folder and recursively delete all its contents.
1542:             */
1543:
1544:            protected void deleteFolder() {
1545:                DefaultMutableTreeNode node = getSelectedNode();
1546:                if (node == root)
1547:                    return;
1548:                if (node == null)
1549:                    return;
1550:                int reply = JOptionPane
1551:                        .showConfirmDialog(this ,
1552:                                "Delete folder and all its contents?",
1553:                                "Delete Folder", JOptionPane.OK_CANCEL_OPTION,
1554:                                JOptionPane.PLAIN_MESSAGE);
1555:                if (reply != JOptionPane.OK_OPTION)
1556:                    return;
1557:
1558:                // if this folder is empty, just delete it
1559:                if (node.isLeaf()) {
1560:                    folderNames.remove(node.getUserObject());
1561:                    model.removeNodeFromParent(node);
1562:                    return;
1563:                }
1564:
1565:                // make a list of nodes to delete
1566:                // because we can't delete nodes while traversing the tree
1567:                ArrayList nodesToDelete = new ArrayList();
1568:                Enumeration nodes = node.breadthFirstEnumeration();
1569:                nodes.nextElement(); // skip the first node which is this node
1570:                while (nodes.hasMoreElements()) {
1571:                    DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) nodes
1572:                            .nextElement();
1573:                    nodesToDelete.add(childNode);
1574:                }
1575:                // delete the leaf nodes and user objects
1576:                for (int i = 0; i < nodesToDelete.size(); i++) {
1577:                    DefaultMutableTreeNode nodeToDelete = (DefaultMutableTreeNode) nodesToDelete
1578:                            .get(i);
1579:                    Object o = nodeToDelete.getUserObject();
1580:                    if (o instanceof  Experiment)
1581:                        deleteExperimentInNode(nodeToDelete);
1582:                    else if (o instanceof  SocietyComponent)
1583:                        deleteSocietyInNode(nodeToDelete);
1584:                    else if (o instanceof  RecipeComponent)
1585:                        deleteRecipeInNode(nodeToDelete);
1586:                    else if (o instanceof  String) // an empty folder
1587:                        model.removeNodeFromParent(nodeToDelete); // just delete the tree node
1588:                }
1589:                // now we're left with the components the user decided not to delete
1590:                // and the folder(s) containing them, but we need to
1591:                // recursively delete the folder(s) that are empty or contain only
1592:                // empty folders
1593:                if (node.isLeaf()) {
1594:                    folderNames.remove(node.getUserObject());
1595:                    model.removeNodeFromParent(node);
1596:                } else
1597:                    deleteEmptyFolders(node);
1598:            }
1599:
1600:            /**
1601:             * Recursively delete empty folders or folders containing only
1602:             * empty folders, starting with the given node.
1603:             */
1604:
1605:            private void deleteEmptyFolders(DefaultMutableTreeNode node) {
1606:                ArrayList nodesToDelete = new ArrayList();
1607:                Enumeration nodes = node.depthFirstEnumeration();
1608:                nodes.nextElement(); // skip the first node which is the start node
1609:                while (nodes.hasMoreElements()) {
1610:                    DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) nodes
1611:                            .nextElement();
1612:                    // if a node is a folder and a leaf, add it to the list to delete
1613:                    Object o = childNode.getUserObject();
1614:                    if (o instanceof  String && childNode.isLeaf())
1615:                        nodesToDelete.add(childNode);
1616:                }
1617:                for (int i = 0; i < nodesToDelete.size(); i++)
1618:                    model
1619:                            .removeNodeFromParent((DefaultMutableTreeNode) nodesToDelete
1620:                                    .get(i));
1621:                // if original folder is now empty, just delete it
1622:                if (node.isLeaf()) {
1623:                    folderNames.remove(node.getUserObject());
1624:                    model.removeNodeFromParent(node);
1625:                    return;
1626:                }
1627:                // if we deleted any nodes, then scan the tree again
1628:                if (nodesToDelete.size() != 0)
1629:                    deleteEmptyFolders(node);
1630:            }
1631:
1632:            /**
1633:             * Delete experiment from database and from workspace if it's there.
1634:             * Don't allow deleting an experiment that's in the console,
1635:             * because that would make it unrunnable.
1636:             */
1637:            protected void deleteExperimentFromDatabase() {
1638:                Map experimentNamesMap = ExperimentDB.getExperimentNames();
1639:                Set keys = experimentNamesMap.keySet();
1640:                JComboBox cb = new JComboBox(keys.toArray(new String[keys
1641:                        .size()]));
1642:                cb.setEditable(false);
1643:                JPanel panel = new JPanel();
1644:                panel.add(new JLabel("Delete Experiment:"));
1645:                panel.add(cb);
1646:                int result = JOptionPane.showConfirmDialog(null, panel,
1647:                        "Delete Experiment", JOptionPane.OK_CANCEL_OPTION,
1648:                        JOptionPane.PLAIN_MESSAGE);
1649:                if (result != JOptionPane.OK_OPTION)
1650:                    return;
1651:                String experimentName = (String) cb.getSelectedItem();
1652:                if (findNodeNamed(experimentName) != null) {
1653:                    JOptionPane
1654:                            .showMessageDialog(
1655:                                    this ,
1656:                                    "You cannot delete an experiment that is in the workspace; delete it from the workspace first.",
1657:                                    "Cannot Delete Experiment",
1658:                                    JOptionPane.ERROR_MESSAGE);
1659:                    return;
1660:                }
1661:                String experimentId = (String) experimentNamesMap
1662:                        .get(experimentName);
1663:                ExperimentDB.deleteExperiment(experimentId, experimentName);
1664:            }
1665:
1666:            /**
1667:             * Delete recipe from database and from workspace if it's there.
1668:             */
1669:            protected void deleteRecipeFromDatabase() {
1670:                Map recipeNamesHT = helper.getRecipeNamesFromDatabase();
1671:                Set dbRecipeNames = recipeNamesHT.keySet();
1672:                if (dbRecipeNames.isEmpty()) {
1673:                    JOptionPane.showMessageDialog(this ,
1674:                            "There are no recipes in the database",
1675:                            "No Database Recipes",
1676:                            JOptionPane.INFORMATION_MESSAGE);
1677:                    return;
1678:                }
1679:                JComboBox cb = new JComboBox(dbRecipeNames.toArray());
1680:                cb.setEditable(false);
1681:                JPanel panel = new JPanel();
1682:                panel.add(new JLabel("Delete Recipe:"));
1683:                panel.add(cb);
1684:                int result = JOptionPane.showConfirmDialog(null, panel,
1685:                        "Delete Recipe", JOptionPane.OK_CANCEL_OPTION,
1686:                        JOptionPane.PLAIN_MESSAGE);
1687:                if (result != JOptionPane.OK_OPTION)
1688:                    return;
1689:                String recipeName = (String) cb.getSelectedItem();
1690:                if (findNodeNamed(recipeName) != null) {
1691:                    JOptionPane
1692:                            .showMessageDialog(
1693:                                    this ,
1694:                                    "You cannot delete a recipe that is in the workspace; delete it from the workspace first.",
1695:                                    "Cannot Delete Recipe",
1696:                                    JOptionPane.ERROR_MESSAGE);
1697:                    return;
1698:                }
1699:                try {
1700:                    helper.deleteRecipe(recipeName);
1701:                } catch (Exception e) {
1702:                    JOptionPane
1703:                            .showMessageDialog(
1704:                                    this ,
1705:                                    "An exception occurred deleting the recipe from the database",
1706:                                    "Error Writing Database",
1707:                                    JOptionPane.ERROR_MESSAGE);
1708:                }
1709:            }
1710:
1711:            ////////////////////////////////
1712:            // Save Experiment or Society in Database
1713:            ///////////////////////////////
1714:
1715:            private void saveInDatabase() {
1716:                DefaultMutableTreeNode node = getSelectedNode();
1717:                if (node == null)
1718:                    return;
1719:                Object o = node.getUserObject();
1720:                if (o == null)
1721:                    return;
1722:                if (o instanceof  Experiment)
1723:                    saveExperiment((DBExperiment) o);
1724:                else if (o instanceof  SocietyComponent)
1725:                    saveSociety((SocietyComponent) o);
1726:                else if (o instanceof  RecipeComponent)
1727:                    saveRecipe((RecipeComponent) o);
1728:            }
1729:
1730:            private void saveExperiment(DBExperiment experiment) {
1731:                final DBExperiment exp = experiment;
1732:                GUIUtils.timeConsumingTaskStart(organizer);
1733:                try {
1734:                    new Thread("Save") {
1735:                        public void run() {
1736:                            exp.save(saveToDbConflictHandler);
1737:                            GUIUtils.timeConsumingTaskEnd(organizer);
1738:                        }
1739:                    }.start();
1740:                } catch (RuntimeException re) {
1741:                    if (log.isErrorEnabled()) {
1742:                        log.error("Error saving experiment: ", re);
1743:                    }
1744:                    GUIUtils.timeConsumingTaskEnd(organizer);
1745:                }
1746:            }
1747:
1748:            private void saveSociety(SocietyComponent society) {
1749:                final SocietyComponent sc = society;
1750:                GUIUtils.timeConsumingTaskStart(organizer);
1751:                try {
1752:                    new Thread("SaveSociety") {
1753:                        public void run() {
1754:                            boolean success = sc.saveToDatabase();
1755:                            GUIUtils.timeConsumingTaskEnd(organizer);
1756:                            if (!success && organizer.log.isWarnEnabled()) {
1757:                                organizer.log.warn("Failed to save society "
1758:                                        + sc.getSocietyName());
1759:                            } else if (organizer.log.isDebugEnabled()) {
1760:                                organizer.log.debug("Saved society "
1761:                                        + sc.getSocietyName());
1762:                            }
1763:                        }
1764:                    }.start();
1765:                } catch (RuntimeException re) {
1766:                    if (log.isErrorEnabled()) {
1767:                        log.error("Runtime exception saving society", re);
1768:                    }
1769:                    GUIUtils.timeConsumingTaskEnd(organizer);
1770:                }
1771:                GUIUtils.timeConsumingTaskEnd(organizer);
1772:            }
1773:
1774:            private void saveRecipe(RecipeComponent recipe) {
1775:                recipe.saveToDatabase();
1776:            }
1777:
1778:            ////////////////////////////////
1779:            // Replace Component in Experiment
1780:            ///////////////////////////////
1781:
1782:            public void replaceComponent(Experiment experiment,
1783:                    ModifiableComponent component,
1784:                    ModifiableComponent newComponent) {
1785:                // find experiment node
1786:                DefaultMutableTreeNode expNode = findNode(experiment);
1787:                if (expNode == null) {
1788:                    if (log.isErrorEnabled()) {
1789:                        log.error("Experiment is not in tree: "
1790:                                + experiment.getExperimentName());
1791:                    }
1792:                    return;
1793:                }
1794:                // find component node in experiment
1795:                DefaultMutableTreeNode componentNode = null;
1796:                Enumeration nodes = expNode.depthFirstEnumeration();
1797:                while (nodes.hasMoreElements()) {
1798:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
1799:                            .nextElement();
1800:                    if (node.getUserObject().equals(component)) {
1801:                        componentNode = node;
1802:                        break;
1803:                    }
1804:                }
1805:                if (componentNode == null) {
1806:                    if (log.isErrorEnabled()) {
1807:                        log.error("Component is not in experiment: "
1808:                                + component.getShortName());
1809:                    }
1810:                    return;
1811:                }
1812:                model.removeNodeFromParent(componentNode);
1813:                if (component instanceof  SocietyComponent) {
1814:                    societyNames.remove(component.getShortName());
1815:                    addSocietyToWorkspace((SocietyComponent) newComponent,
1816:                            expNode);
1817:                } else if (component instanceof  RecipeComponent) {
1818:                    recipeNames.remove(component.getShortName());
1819:                    addRecipeToWorkspace((RecipeComponent) newComponent,
1820:                            expNode);
1821:                }
1822:            }
1823:
1824:            ////////////////////////////////
1825:            // Add and remove nodes for children of an experiment
1826:            ////////////////////////////////
1827:
1828:            /**
1829:             * Add tree nodes for the children (societies and recipes)
1830:             * of an experiment.  First removes any current children nodes.
1831:             * @param experiment the experiment for which to add children
1832:             */
1833:            public void addChildren(Experiment experiment) {
1834:                DefaultMutableTreeNode expNode = findNode(experiment);
1835:                // first remove old nodes
1836:                int n = expNode.getChildCount();
1837:                for (int i = 0; i < n; i++) {
1838:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) expNode
1839:                            .getChildAt(0);
1840:                    model.removeNodeFromParent(node);
1841:                }
1842:                SocietyComponent society = experiment.getSocietyComponent();
1843:                if (society != null)
1844:                    addSocietyToWorkspace(society, expNode);
1845:                RecipeComponent[] recipes = experiment.getRecipeComponents();
1846:                for (int i = 0; i < recipes.length; i++)
1847:                    addRecipeToWorkspace(recipes[i], expNode);
1848:                workspace.setSelection(expNode);
1849:            }
1850:
1851:            /**
1852:             * Display tree nodes for the children (societies and recipes)
1853:             * of an experiment in gray and don't let them be edited.
1854:             * Used when editing the experiment.
1855:             * @param experiment the experiment
1856:             */
1857:            protected void removeChildren(Experiment experiment) {
1858:                DefaultMutableTreeNode expNode = findNode(experiment);
1859:                int n = expNode.getChildCount();
1860:                // display these nodes in gray and don't let them be edited
1861:                for (int i = 0; i < n; i++) {
1862:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) expNode
1863:                            .getChildAt(i);
1864:                    model.nodeChanged(node);
1865:                }
1866:            }
1867:
1868:            ////////////////////////////////
1869:            // Display names of experiments containing societies or recipes
1870:            ///////////////////////////////
1871:
1872:            /**
1873:             * Display names of experiments in workspace or database
1874:             * that contain the indicated society.
1875:             */
1876:            public void displayExperiments(SocietyComponent society) {
1877:                Set experimentNames = DBUtils
1878:                        .dbGetExperimentsWithSociety(society.getSocietyName());
1879:                experimentNames.addAll(getExperimentNamesInWorkspace(society));
1880:                if (experimentNames.size() == 0)
1881:                    return; // no experiments were affected
1882:                displayExperimentList(experimentNames);
1883:            }
1884:
1885:            private void displayExperimentsInWorkspace(SocietyComponent society) {
1886:                ArrayList experimentNames = getExperimentNamesInWorkspace(society);
1887:                if (experimentNames.size() == 0)
1888:                    return; // no experiments were affected
1889:                displayExperimentList(experimentNames);
1890:            }
1891:
1892:            /**
1893:             * Display names of experiments in workspace or database
1894:             * that contain the indicated recipe.
1895:             * @param recipe the recipe component
1896:             */
1897:            public void displayExperiments(RecipeComponent recipe) {
1898:                Set experimentNames = DBUtils.dbGetExperimentsWithRecipe(recipe
1899:                        .getRecipeName());
1900:                experimentNames.addAll(getExperimentNamesInWorkspace(recipe));
1901:                if (experimentNames.size() == 0)
1902:                    return; // no experiments were affected
1903:                displayExperimentList(experimentNames);
1904:            }
1905:
1906:            private void displayExperimentsInWorkspace(RecipeComponent recipe) {
1907:                ArrayList experimentNames = getExperimentNamesInWorkspace(recipe);
1908:                if (experimentNames.size() == 0)
1909:                    return; // no experiments were affected
1910:                displayExperimentList(experimentNames);
1911:            }
1912:
1913:            /**
1914:             * Get experiments from workspace.
1915:             */
1916:            private ArrayList getExperiments() {
1917:                ArrayList experiments = new ArrayList();
1918:                Enumeration nodes = root.depthFirstEnumeration();
1919:                while (nodes.hasMoreElements()) {
1920:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
1921:                            .nextElement();
1922:                    Object o = node.getUserObject();
1923:                    if (o instanceof  Experiment)
1924:                        experiments.add(o);
1925:                }
1926:                return experiments;
1927:            }
1928:
1929:            /**
1930:             * Get names of experiments in workspace that contain the society.
1931:             * Mark the experiments as modified.
1932:             */
1933:            private ArrayList getExperimentNamesInWorkspace(
1934:                    SocietyComponent society) {
1935:                ArrayList results = new ArrayList();
1936:                ArrayList experiments = getExperiments();
1937:                for (int i = 0; i < experiments.size(); i++) {
1938:                    Experiment experiment = (Experiment) experiments.get(i);
1939:                    SocietyComponent sc = experiment.getSocietyComponent();
1940:                    if (sc != null && sc.equals(society))
1941:                        results.add(experiment.getExperimentName());
1942:                }
1943:                return results;
1944:            }
1945:
1946:            /**
1947:             * Get names of experiments in workspace that contain the recipe.
1948:             * Mark the experiments as modified.
1949:             */
1950:            private ArrayList getExperimentNamesInWorkspace(
1951:                    RecipeComponent recipe) {
1952:                ArrayList results = new ArrayList();
1953:                ArrayList experiments = getExperiments();
1954:                for (int i = 0; i < experiments.size(); i++) {
1955:                    Experiment experiment = (Experiment) experiments.get(i);
1956:                    RecipeComponent[] recipes = experiment
1957:                            .getRecipeComponents();
1958:                    for (int j = 0; j < recipes.length; j++) {
1959:                        if (recipes[j].equals(recipe)) {
1960:                            results.add(experiment.getExperimentName());
1961:                            break;
1962:                        }
1963:                    }
1964:                }
1965:                return results;
1966:            }
1967:
1968:            /**
1969:             * Display the names of experiments affected by a change
1970:             * to their society or recipes.
1971:             */
1972:            private void displayExperimentList(Collection names) {
1973:                Frame frame = null;
1974:                try {
1975:                    frame = JOptionPane.getFrameForComponent(this );
1976:                } catch (Exception e) {
1977:                    if (log.isErrorEnabled()) {
1978:                        log.error("Could not get frame for Organizer: " + e);
1979:                    }
1980:                }
1981:                final JDialog dialog = new JDialog(frame,
1982:                        "Experiments That Must Be Saved", true);
1983:                dialog.getContentPane().setLayout(new BorderLayout());
1984:                JPanel panel = new JPanel();
1985:                panel.setLayout(new GridBagLayout());
1986:                int x = 0;
1987:                int y = 0;
1988:                JTextArea msg = new JTextArea(
1989:                        "The following experiments must be saved to the database in order to be updated:",
1990:                        3, 100);
1991:                msg.setLineWrap(true);
1992:                msg.setWrapStyleWord(true);
1993:                msg.setBackground(panel.getBackground());
1994:                panel.add(msg, new GridBagConstraints(x, y++, 1, 1, 0.0, 0.0,
1995:                        GridBagConstraints.CENTER, GridBagConstraints.NONE,
1996:                        new Insets(10, 5, 5, 5), 0, 0));
1997:                Vector sortedNames = new Vector(names);
1998:                Collections.sort(sortedNames);
1999:                JList namesList = new JList(sortedNames);
2000:                namesList.setBackground(panel.getBackground());
2001:                JScrollPane jsp = new JScrollPane(namesList);
2002:                jsp.setMinimumSize(new Dimension(100, 50));
2003:                panel.add(jsp, new GridBagConstraints(x, y++, 1, 1, 1.0, 1.0,
2004:                        GridBagConstraints.CENTER, GridBagConstraints.BOTH,
2005:                        new Insets(0, 5, 0, 5), 0, 0));
2006:                JButton okButton = new JButton("OK");
2007:                okButton.addActionListener(new ActionListener() {
2008:                    public void actionPerformed(ActionEvent e) {
2009:                        dialog.dispose();
2010:                    }
2011:                });
2012:                JPanel buttonPanel = new JPanel();
2013:                buttonPanel.add(okButton);
2014:                dialog.getContentPane().add(panel, BorderLayout.CENTER);
2015:                dialog.getContentPane().add(buttonPanel, BorderLayout.SOUTH);
2016:                dialog.setSize(400, 300);
2017:                dialog.setVisible(true);
2018:            }
2019:
2020:            ////////////////////////////////
2021:            // Utilities
2022:            ///////////////////////////////
2023:
2024:            private void installListeners(ModifiableComponent component) {
2025:                component.addModificationListener(myModificationListener);
2026:            }
2027:
2028:            /**
2029:             * The following methods:
2030:             * create a new tree node for the component,
2031:             * add the new node to the workspace as the last child of the specified node,
2032:             * add the component name to the appropriate list of unique names,
2033:             * add the listeners for the component, and
2034:             * set the workspace selection to be the new node.
2035:             */
2036:            private DefaultMutableTreeNode addExperimentToWorkspace(
2037:                    DBExperiment experiment, DefaultMutableTreeNode node) {
2038:                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
2039:                        experiment, true);
2040:                addNode(node, newNode);
2041:                experimentNames.add(experiment.getExperimentName());
2042:                workspace.setSelection(newNode);
2043:                installListeners(experiment);
2044:                return newNode;
2045:            }
2046:
2047:            private DefaultMutableTreeNode addSocietyToWorkspace(
2048:                    SocietyComponent sc, DefaultMutableTreeNode node) {
2049:                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(sc,
2050:                        false);
2051:                addNode(node, newNode);
2052:                societyNames.add(sc.getSocietyName());
2053:                workspace.setSelection(newNode);
2054:                installListeners(sc);
2055:                return newNode;
2056:            }
2057:
2058:            protected DefaultMutableTreeNode addRecipeToWorkspace(
2059:                    RecipeComponent recipe, DefaultMutableTreeNode node) {
2060:                if (recipe == null)
2061:                    return null;
2062:                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
2063:                        recipe, false);
2064:                addNode(node, newNode);
2065:                recipeNames.add(recipe.getRecipeName());
2066:                workspace.setSelection(newNode);
2067:                installListeners(recipe);
2068:                return newNode;
2069:            }
2070:
2071:            protected DefaultMutableTreeNode addFolderToWorkspace(String name,
2072:                    DefaultMutableTreeNode node) {
2073:                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(
2074:                        name, true);
2075:                addNode(node, newNode);
2076:                folderNames.add(name);
2077:                workspace.setSelection(newNode);
2078:                return newNode;
2079:            }
2080:
2081:            /**
2082:             * Add newNode as last child of node.
2083:             */
2084:            private void addNode(DefaultMutableTreeNode node,
2085:                    DefaultMutableTreeNode newNode) {
2086:                if (node == null)
2087:                    node = root;
2088:                model.insertNodeInto(newNode, node, node.getChildCount());
2089:                workspace.scrollPathToVisible(new TreePath(newNode.getPath()));
2090:            }
2091:
2092:            /**
2093:             * Find a node containing the user object.
2094:             * WARNING: societies and recipes may be in more than one node,
2095:             * this just returns the first node found
2096:             */
2097:            private DefaultMutableTreeNode findNode(Object userObject) {
2098:                Enumeration nodes = root.depthFirstEnumeration();
2099:                while (nodes.hasMoreElements()) {
2100:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
2101:                            .nextElement();
2102:                    if (node.getUserObject().equals(userObject))
2103:                        return node;
2104:                }
2105:                return null;
2106:            }
2107:
2108:            private DefaultMutableTreeNode findNodeNamed(String s) {
2109:                Enumeration nodes = root.depthFirstEnumeration();
2110:                while (nodes.hasMoreElements()) {
2111:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
2112:                            .nextElement();
2113:                    if (node.toString().equals(s))
2114:                        return node;
2115:                }
2116:                return null;
2117:            }
2118:
2119:            /**
2120:             * If the selected node is in an experiment, return true.
2121:             */
2122:            private boolean isSelectedNodeInExperiment() {
2123:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) getSelectedNode()
2124:                        .getParent();
2125:                if (parentNode.getUserObject() != null
2126:                        && parentNode.getUserObject() instanceof  Experiment)
2127:                    return true;
2128:                return false;
2129:            }
2130:
2131:            /**
2132:             * Fully expand the tree; called in initialization
2133:             * so that the initial view of the tree is fully expanded.
2134:             */
2135:            private void expandTree() {
2136:                Enumeration nodes = root.depthFirstEnumeration();
2137:                while (nodes.hasMoreElements()) {
2138:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
2139:                            .nextElement();
2140:                    workspace.expandPath(new TreePath(node.getPath()));
2141:                }
2142:            }
2143:
2144:            /**
2145:             * Returns true if the object is
2146:             * a component (a society or recipe) in an experiment
2147:             * that is being built or run.
2148:             */
2149:            protected boolean isComponentInUse(ModifiableComponent mc) {
2150:                Enumeration nodes = root.depthFirstEnumeration();
2151:                while (nodes.hasMoreElements()) {
2152:                    DefaultMutableTreeNode node = (DefaultMutableTreeNode) nodes
2153:                            .nextElement();
2154:                    Object o = node.getUserObject();
2155:                    if (o instanceof  Experiment) {
2156:                        Experiment exp = (Experiment) o;
2157:                        if (CSMART.isExperimentInConsole(exp)
2158:                                || CSMART.isExperimentInEditor(exp))
2159:                            if (exp.getComponents().contains(mc))
2160:                                return true;
2161:                    }
2162:                }
2163:                return false;
2164:            }
2165:
2166:            /**
2167:             * Returns true if the node is in an experiment node
2168:             * and the experiment is being built or run.
2169:             */
2170:            protected boolean isNodeInUse(DefaultMutableTreeNode node) {
2171:                DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) node
2172:                        .getParent();
2173:                if (parentNode == null)
2174:                    return false;
2175:                Object parentObject = parentNode.getUserObject();
2176:                if (parentObject instanceof  Experiment) {
2177:                    Experiment exp = (Experiment) parentObject;
2178:                    if (CSMART.isExperimentInConsole(exp)
2179:                            || CSMART.isExperimentInEditor(exp))
2180:                        return true;
2181:                }
2182:                return false;
2183:            }
2184:
2185:            ////////////////////////////////
2186:            // Title utilities
2187:            ///////////////////////////////
2188:
2189:            private void setFrameTitle() {
2190:                setFrameTitle(workspace.getSelectionPath());
2191:            }
2192:
2193:            private void setFrameTitle(TreePath newSelection) {
2194:                String doc;
2195:                if (newSelection != null) {
2196:                    doc = newSelection.toString();
2197:                } else {
2198:                    doc = null;
2199:                }
2200:                setFrameTitleDocument(doc);
2201:            }
2202:
2203:            private void setFrameTitleDocument(String doc) {
2204:                JFrame frame = (JFrame) SwingUtilities.getAncestorOfClass(
2205:                        JFrame.class, workspace);
2206:                if (frame == null)
2207:                    return;
2208:                String oldTitle = frame.getTitle();
2209:                if (oldTitle == null) {
2210:                    oldTitle = FRAME_TITLE;
2211:                } else {
2212:                    int colon = oldTitle.indexOf(':');
2213:                    if (colon >= 0)
2214:                        oldTitle = oldTitle.substring(0, colon).trim();
2215:                }
2216:                if (doc == null)
2217:                    frame.setTitle(oldTitle);
2218:                else
2219:                    frame.setTitle(oldTitle + ":" + doc);
2220:            }
2221:
2222:            ///////////////////////////////////////////
2223:            // workspace listeners
2224:            ///////////////////////////////////////////
2225:
2226:            private TreeModelListener myModelListener = new TreeModelListener() {
2227:                public void treeNodesChanged(TreeModelEvent e) {
2228:                    if (doWorkspace)
2229:                        update();
2230:                }
2231:
2232:                public void treeNodesInserted(TreeModelEvent e) {
2233:                    if (doWorkspace)
2234:                        update();
2235:                }
2236:
2237:                public void treeNodesRemoved(TreeModelEvent e) {
2238:                    if (doWorkspace)
2239:                        update();
2240:                }
2241:
2242:                public void treeStructureChanged(TreeModelEvent e) {
2243:                    if (doWorkspace)
2244:                        update();
2245:                }
2246:            };
2247:
2248:            /**
2249:             * Called when selection in organizer tree is changed.
2250:             */
2251:            private TreeSelectionListener mySelectionListener = new TreeSelectionListener() {
2252:                public void valueChanged(TreeSelectionEvent e) {
2253:                    setFrameTitle(e.getNewLeadSelectionPath());
2254:                }
2255:            };
2256:
2257:            private AncestorListener myAncestorListener = new AncestorListener() {
2258:                public void ancestorAdded(AncestorEvent e) {
2259:                    setFrameTitle();
2260:                }
2261:
2262:                public void ancestorRemoved(AncestorEvent e) {
2263:                }
2264:
2265:                public void ancestorMoved(AncestorEvent e) {
2266:                }
2267:            };
2268:
2269:            protected void addTreeSelectionListener(
2270:                    TreeSelectionListener listener) {
2271:                workspace.addTreeSelectionListener(listener);
2272:            }
2273:
2274:            protected void addTreeModelListener(TreeModelListener listener) {
2275:                model.addTreeModelListener(listener);
2276:            }
2277:
2278:            ///////////////////////////////////////
2279:            // Restore (read from file) and save workspace.
2280:            ///////////////////////////////////////
2281:
2282:            private void restore(String fileName) {
2283:                try {
2284:                    if (!fileName.endsWith(".xml"))
2285:                        fileName = fileName + ".xml";
2286:                    this .workspaceFileName = fileName;
2287:
2288:                    root = new DefaultMutableTreeNode();
2289:                    String label = workspaceFileName;
2290:                    label = label.substring(0, label.lastIndexOf('.'));
2291:                    root.setUserObject(label);
2292:
2293:                    // Must set up the model, workspace before actually doing the
2294:                    // load since the helper methods need this infrastructure
2295:                    model = new DefaultTreeModel(root);
2296:
2297:                    if (doWorkspace) {
2298:                        // set the selected node to be the root node
2299:                        workspace = new OrganizerTree(model);
2300:                        workspace.setSelection(root);
2301:                    }
2302:
2303:                    try {
2304:                        experimentNames.init(root, DBExperiment.class,
2305:                                "getExperimentName");
2306:                        societyNames.init(root, SocietyComponent.class,
2307:                                "getSocietyName");
2308:                        recipeNames.init(root, RecipeComponent.class,
2309:                                "getRecipeName");
2310:                        folderNames.init(root, String.class, "toString");
2311:                    } catch (SecurityException se) {
2312:                        if (log.isErrorEnabled()) {
2313:                            log
2314:                                    .error(
2315:                                            "Organizer error restoring workspace",
2316:                                            se);
2317:                        }
2318:                    }
2319:
2320:                    if (doWorkspace) {
2321:                        OrganizerXML oxml = new OrganizerXML();
2322:                        oxml.populateWorkspace(fileName, this );
2323:                    } else {
2324:                        if (log.isInfoEnabled()) {
2325:                            log.info("Not reading workspace file " + fileName);
2326:                        }
2327:                    }
2328:
2329:                } catch (Exception ioe) {
2330:                    if (log.isErrorEnabled()) {
2331:                        log.error("Organizer error restoring workspace", ioe);
2332:                    }
2333:                    return;
2334:                }
2335:            } // end of restore
2336:
2337:            /**
2338:             * Call update if anything changed.
2339:             */
2340:            private transient ModificationListener myModificationListener = new ModificationListener() {
2341:                public void modified(ModificationEvent event) {
2342:                    DefaultMutableTreeNode changedNode = findNode(event
2343:                            .getSource());
2344:                    if (changedNode != null) {
2345:                        model.nodeChanged(changedNode);
2346:                        // this could be an experiment saved, which would make it runnable
2347:                        // which should change which tools are enabled
2348:                        csmart.enableCSMARTTools();
2349:                    }
2350:                    if (doWorkspace)
2351:                        update();
2352:                }
2353:            };
2354:
2355:            protected boolean exitAllowed() {
2356:                if (doWorkspace) {
2357:                    synchronized (lockObject) {
2358:                        if (updateNeeded) {
2359:                            nextUpdate = System.currentTimeMillis();
2360:                            lockObject.notify();
2361:                            while (updateNeeded) {
2362:                                try {
2363:                                    lockObject.wait();
2364:                                } catch (InterruptedException ie) {
2365:                                }
2366:                            }
2367:                        }
2368:                    }
2369:                }
2370:                return true;
2371:            }
2372:
2373:            /**
2374:             * Force an update, which saves the current workspace.
2375:             */
2376:            protected void save() {
2377:                if (doWorkspace)
2378:                    update();
2379:            }
2380:
2381:            private void save(String fileName) {
2382:                if (!doWorkspace)
2383:                    return;
2384:
2385:                if (log.isDebugEnabled()) {
2386:                    log.debug("Saving to: " + fileName);
2387:                }
2388:
2389:                if (!fileName.endsWith(".xml"))
2390:                    fileName = fileName + ".xml";
2391:
2392:                try {
2393:                    // Write out the workspace as an XML file
2394:                    OrganizerXML oxml = new OrganizerXML();
2395:                    try {
2396:                        oxml.writeXMLFile(new File("."), oxml
2397:                                .createXMLDocument(root, csmart.getResultDir()
2398:                                        .getPath()), fileName);
2399:                    } catch (IOException ioe) {
2400:                        if (log.isErrorEnabled()) {
2401:                            log
2402:                                    .error(
2403:                                            "Caught an Exception trying to write Organizer XML File",
2404:                                            ioe);
2405:                        }
2406:                    }
2407:
2408:                } catch (Exception ioe) {
2409:                    if (log.isErrorEnabled()) {
2410:                        log.error("Organizer error saving workspace", ioe);
2411:                    }
2412:                }
2413:            }
2414:
2415:            private Thread updater = new Thread() {
2416:                public void start() {
2417:                    updateNeeded = false;
2418:                    if (doWorkspace)
2419:                        super .start();
2420:                }
2421:
2422:                public void run() {
2423:                    if (!doWorkspace)
2424:                        return;
2425:                    synchronized (lockObject) {
2426:                        while (true) {
2427:                            try {
2428:                                long now = System.currentTimeMillis();
2429:                                if (updateNeeded && now > nextUpdate) {
2430:                                    save(workspaceFileName);
2431:                                    updateNeeded = false;
2432:                                    lockObject.notifyAll(); // In case anyone's waiting for the update to finish
2433:                                } else if (updateNeeded) {
2434:                                    long delay = nextUpdate - now;
2435:                                    if (delay > 0) {
2436:                                        lockObject.wait(delay);
2437:                                    }
2438:                                } else {
2439:                                    lockObject.wait();
2440:                                }
2441:                            } catch (InterruptedException ie) {
2442:                            }
2443:                        }
2444:                    }
2445:                }
2446:            };
2447:
2448:            private void update() {
2449:                if (!doWorkspace)
2450:                    return;
2451:                synchronized (lockObject) {
2452:                    nextUpdate = System.currentTimeMillis() + UPDATE_DELAY;
2453:                    updateNeeded = true;
2454:                    lockObject.notify();
2455:                }
2456:            }
2457:
2458:            ////////////////////////////////////////////
2459:
2460:            // Class for holding name/Class pairs in UIs
2461:            private static class NameClassItem {
2462:                public String name;
2463:                public Class cls;
2464:
2465:                public NameClassItem(String name, Class cls) {
2466:                    this .cls = cls;
2467:                    this .name = name;
2468:                }
2469:
2470:                public String toString() {
2471:                    return name;
2472:                }
2473:            }
2474:
2475:            private void readObject(ObjectInputStream ois) throws IOException,
2476:                    ClassNotFoundException {
2477:                ois.defaultReadObject();
2478:                createLogger();
2479:            }
2480:
2481:        } // end of Organizer class
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.