001/*
002 * Copyright (c) 2009-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2014-08-15 18:04:13 +0000 (Fri, 15 Aug 2014) $' 
007 * '$Revision: 32889 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.kepler.modulemanager.gui;
031
032import java.awt.Color;
033import java.awt.event.ActionEvent;
034import java.awt.event.ActionListener;
035import java.io.File;
036import java.io.FileNotFoundException;
037import java.util.ArrayList;
038import java.util.List;
039
040import javax.swing.DefaultListModel;
041import javax.swing.JButton;
042import javax.swing.JFileChooser;
043import javax.swing.JLabel;
044import javax.swing.JList;
045import javax.swing.JOptionPane;
046import javax.swing.JPanel;
047import javax.swing.JScrollPane;
048import javax.swing.ListModel;
049import javax.swing.SwingWorker;
050import javax.swing.event.ListSelectionEvent;
051import javax.swing.event.ListSelectionListener;
052
053import org.apache.tools.ant.DefaultLogger;
054import org.apache.tools.ant.Project;
055import org.apache.tools.ant.taskdefs.Copy;
056import org.jdesktop.layout.GroupLayout;
057import org.kepler.build.Run;
058import org.kepler.build.modules.CurrentSuiteTxt;
059import org.kepler.build.modules.Module;
060import org.kepler.build.modules.ModuleTree;
061import org.kepler.build.modules.ModulesTxt;
062import org.kepler.build.project.ProjectLocator;
063import org.kepler.build.util.Version;
064import org.kepler.modulemanager.ModuleDownloader;
065import org.kepler.util.ShutdownNotifier;
066
067import ptolemy.gui.GraphicalMessageHandler;
068import ptolemy.gui.JFileChooserBugFix;
069import ptolemy.gui.PtFileChooser;
070import ptolemy.gui.PtFilenameFilter;
071import ptolemy.gui.PtGUIUtilities;
072import ptolemy.util.MessageHandler;
073
074/**
075 * Created by David Welker.
076 * Date: Oct 7, 2009
077 * Time: 6:33:12 PM
078 */
079public class CurrentSuitePanel extends JPanel
080{
081    private static String CURRENT_SUITE_LABEL_TEXT = 
082        "<html><p><font color=blue>If you're seeing this dialog when trying to launch Kepler, " +
083        "Kepler had a problem starting up.</font></p><p><font color=blue>Please select a suite " +
084        "from the Available Suites and Modules tab and click Apply and Restart.</font></p>" +
085        "<p>Current Suite:</p></html>";
086    private JLabel currentSuiteListLabel = new JLabel(CURRENT_SUITE_LABEL_TEXT);
087    private JList currentSuiteList = new JList();
088    private JScrollPane activeModulesListScrollPane = new JScrollPane(currentSuiteList);
089
090    private JButton saveConfiguration = new JButton("Save Suite");
091    private JButton loadConfiguration = new JButton("Load Suite");
092
093    private ModuleDownloader downloader;
094
095    public CurrentSuitePanel()
096    {
097        super();
098        initComponents();
099        layoutComponents();
100    }
101
102    private void initActiveModulesList()
103    {
104        String currentSuiteName = CurrentSuiteTxt.getName();
105        if( currentSuiteName.equals("unknown") )
106        {
107            currentSuiteName = "custom";
108        }
109        currentSuiteListLabel.setText(CURRENT_SUITE_LABEL_TEXT + currentSuiteName );
110
111        DefaultListModel listModel = new DefaultListModel();
112        ModulesTxt.init();
113        for(Module module : ModuleTree.instance())
114        {
115            listModel.addElement(module.toString());
116        }
117        currentSuiteList.setModel(listModel);
118    }
119
120    private void initComponents()
121    {
122        initActiveModulesList();
123        downloader = new ModuleDownloader();
124        ModuleDownloadProgressMonitor mdpm = new ModuleDownloadProgressMonitor(this);
125        downloader.addListener(mdpm);
126
127        currentSuiteList.addListSelectionListener(new ListSelectionListener()
128        {
129            @Override
130            public void valueChanged(ListSelectionEvent e)
131            {
132                currentSuiteList.clearSelection();
133            }
134        });
135
136        saveConfiguration.addActionListener( new ActionListener()
137        {
138
139            @Override
140            public void actionPerformed(ActionEvent e)
141            {
142                // Avoid white boxes in file chooser, see
143                // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3801
144                JFileChooserBugFix jFileChooserBugFix = new JFileChooserBugFix();
145                Color background = null;
146                PtFileChooser fc = new PtFileChooser(null, "Save Suite", JFileChooser.SAVE_DIALOG);
147                try {
148                    background = jFileChooserBugFix.saveBackground();
149                    fc.setSelectedFile(new File("unnamed.txt"));
150                    int returnValue = fc.showDialog(CurrentSuitePanel.this, "Save");
151                    File saveToFile = fc.getSelectedFile();
152                    if(saveToFile.exists() && !PtGUIUtilities.useFileDialog()) {
153                        if(MessageHandler.yesNoQuestion("Overwrite \""
154                                + saveToFile.getName() + "\"?")) {
155                                returnValue = JFileChooser.APPROVE_OPTION;
156                        } else {
157                                returnValue = JFileChooser.CANCEL_OPTION;
158                        }
159                    }
160                    if( returnValue == JFileChooser.APPROVE_OPTION )
161                        {
162                            Copy copy = new Copy();
163                            copy.setFile(ModulesTxt.instance());
164                            copy.setTofile(saveToFile);
165                            copy.execute();
166                        }
167                        } finally {
168                            jFileChooserBugFix.restoreBackground(background);
169                        }
170            }
171        });
172
173        loadConfiguration.addActionListener( new ActionListener()
174        {
175
176            @Override
177            public void actionPerformed(ActionEvent e)
178            {
179                PtFileChooser fc = new PtFileChooser(null, "Load Suite", JFileChooser.OPEN_DIALOG);
180                
181                fc.addChoosableFileFilter(new PtFilenameFilter()
182                {
183                        @Override
184                    public boolean accept(File f)
185                    {
186                        return f.getName().endsWith(".txt");
187                    }
188
189                        @Override
190                    public String getDescription()
191                    {
192                        return "Module configuration files.";
193                    }
194                });
195                int returnValue = fc.showDialog(CurrentSuitePanel.this, "Load Configuration");
196                if( returnValue == JFileChooser.APPROVE_OPTION )
197                {
198                    System.out.println("Load");
199
200                    File loadFromFile = fc.getSelectedFile();
201                    Copy copy = new Copy();
202                    copy.setOverwrite(true);           
203                    copy.setFile(loadFromFile);
204                    copy.setTofile(ModulesTxt.instance());
205                    copy.execute();
206                    initActiveModulesList();
207
208                    JOptionPane.showMessageDialog(CurrentSuitePanel.this, "Restarting...");
209                    SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>()
210                    {
211                        @Override
212                        public Void doInBackground() throws Exception
213                        {
214                            saveConfiguration.setEnabled(false);
215                            loadConfiguration.setEnabled(false);
216
217                            ListModel listModel = currentSuiteList.getModel();
218                            List<String> moduleList = new ArrayList();
219                            for (int i = 0; i < listModel.getSize(); i++)
220                              moduleList.add((String) listModel.getElementAt(i));
221                            try {
222                                downloader.downloadModules(moduleList);
223                            } catch (FileNotFoundException e) {
224                                JOptionPane.showMessageDialog(
225                                        CurrentSuitePanel.this,
226                                          e.getMessage());
227                            }                            
228                            return null;
229                        }
230
231                        @Override
232                        protected void done()
233                        {
234                            Project project = new Project();
235                            project.setBaseDir(ProjectLocator.getProjectDir());
236                            DefaultLogger logger = new DefaultLogger();
237                            logger.setMessageOutputLevel(Project.MSG_INFO);
238                            logger.setOutputPrintStream(System.out);
239                            logger.setErrorPrintStream(System.out);
240                            project.addBuildListener(logger);
241
242                            //XXX call ShutdownNotifer.shutdown() before spawning new process,
243                            // to avoid 2nd instance potentially interfering with quitting first.
244                            // see: http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5484
245                            System.out.println("CurrentSuitePanel notifiying shutdown listeners " +
246                                        "of impending shutdown. Any open databases may take awhile to close...");
247                            ShutdownNotifier.shutdown();
248                            
249                            Run run = new Run();
250                            run.setTaskName("run");
251                            run.setProject(project);
252                            run.init();
253                            run.setSpawn(true);
254                            run.execute();
255
256                            //TODO why call exit with error arg here?
257                            System.exit(1);
258                        }
259
260                    };
261                    worker.execute();
262                }
263            }
264        });
265
266    }
267
268    private void layoutComponents()
269    {
270        GroupLayout layout = new GroupLayout(this);
271        setLayout(layout);
272        layout.setAutocreateContainerGaps(true);
273        layout.setAutocreateGaps(true);
274
275        layout.setHorizontalGroup
276        (
277            layout.createParallelGroup()
278                .add(currentSuiteListLabel)
279                .add(activeModulesListScrollPane)
280                .add( layout.createSequentialGroup()
281                    .add(saveConfiguration)
282                    .add(loadConfiguration))
283        );
284
285        layout.setVerticalGroup
286        (
287            layout.createSequentialGroup()
288                .add(currentSuiteListLabel)
289                .add(activeModulesListScrollPane)
290                .add(layout.createParallelGroup()
291                    .add(saveConfiguration)
292                    .add(loadConfiguration))
293        );
294    }
295
296    /** Perform sanity checks on the suite to see if Kepler will start
297     *  using that suite. If it appears that Kepler will not start,
298     *  ask the user if they really want to exit the Module Manager.
299     * 
300     * @return returns true if the Module Manager can exit.
301     */
302        public static boolean canExit() {
303            
304            //System.out.println("Performing sanity checks for selected suite.");
305            
306            boolean retval = true;
307            
308            GraphicalMessageHandler handler = new GraphicalMessageHandler();
309            MessageHandler.setMessageHandler(handler);
310            
311            final ModulesTxt modulesTxt = ModulesTxt.instance();
312            
313            // read the modules txt file
314            modulesTxt.read();
315            
316            // see if kepler suite is found
317            ModuleTree tree = new ModuleTree(modulesTxt);
318            if(tree.getModuleByStemName("kepler") == null) {
319                
320                // check the suite name
321                CurrentSuiteTxt.init();
322                String suiteName = CurrentSuiteTxt.getName();
323                if(!suiteName.equals("kepler") && !Version.stem(suiteName).equals("kepler")) {
324                retval = MessageHandler.yesNoQuestion("The current suite does not contain the kepler module.\n" +
325                                "Kepler will most likely not start with this suite.\n" +
326                        "Do you still want to exit the Module Manager?");
327                }
328                
329            }
330            /* This is commented out since allModulesPresent() can incorrectly return false.
331             * If use.keplerdata exists, allModulesPresent() appears to only look for modules
332             * in kepler.modules and not where Kepler is installed.
333            else if(!tree.allModulesPresent()) {
334                StringBuilder message = new StringBuilder("The following modules are not present: ");
335                for(Module module : tree.getMissingModules()) {
336                    message.append("\n" + module.getName());
337                }
338                message.append("\n");
339                message.append("Do you still want to exit the Module Manager?");
340                retval = MessageHandler.yesNoQuestion(message.toString());
341            }
342            */
343            
344            return retval;
345            
346        }
347}