001/**
002 *  '$Author: crawl $'
003 *  '$Date: 2015-11-02 18:39:49 +0000 (Mon, 02 Nov 2015) $'
004 *  '$Revision: 34180 $'
005 *
006 *  For Details:
007 *  http://www.kepler-project.org
008 *
009 *  Copyright (c) 2009-2010 The Regents of the
010 *  University of California. All rights reserved. Permission is hereby granted,
011 *  without written agreement and without license or royalty fees, to use, copy,
012 *  modify, and distribute this software and its documentation for any purpose,
013 *  provided that the above copyright notice and the following two paragraphs
014 *  appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF
015 *  CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
016 *  OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
017 *  DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
018 *  POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY
019 *  DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
020 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
021 *  SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
022 *  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
023 *  ENHANCEMENTS, OR MODIFICATIONS.
024 */
025
026package org.kepler.workflowrunmanager.gui;
027
028import java.awt.BorderLayout;
029import java.awt.Component;
030import java.awt.Cursor;
031import java.awt.Dimension;
032import java.awt.FlowLayout;
033import java.awt.Font;
034import java.awt.event.ActionEvent;
035import java.awt.event.ActionListener;
036import java.awt.event.FocusEvent;
037import java.awt.event.FocusListener;
038import java.awt.event.WindowAdapter;
039import java.awt.event.WindowEvent;
040import java.beans.PropertyChangeEvent;
041import java.beans.PropertyChangeListener;
042import java.io.File;
043import java.io.IOException;
044import java.text.DateFormat;
045import java.util.ArrayList;
046import java.util.Collection;
047import java.util.HashMap;
048import java.util.HashSet;
049import java.util.Iterator;
050import java.util.List;
051import java.util.ListIterator;
052import java.util.Map;
053import java.util.Set;
054import java.util.Vector;
055import java.util.concurrent.Executors;
056
057import javax.swing.DefaultCellEditor;
058import javax.swing.JButton;
059import javax.swing.JComboBox;
060import javax.swing.JLabel;
061import javax.swing.JList;
062import javax.swing.JMenuItem;
063import javax.swing.JOptionPane;
064import javax.swing.JPanel;
065import javax.swing.JPopupMenu;
066import javax.swing.JScrollPane;
067import javax.swing.JTable;
068import javax.swing.JTextField;
069import javax.swing.JToolBar;
070import javax.swing.ListCellRenderer;
071import javax.swing.SwingWorker;
072import javax.swing.event.CellEditorListener;
073import javax.swing.event.ChangeEvent;
074import javax.swing.event.ListSelectionEvent;
075import javax.swing.event.ListSelectionListener;
076import javax.swing.table.TableCellEditor;
077import javax.swing.table.TableColumn;
078
079import org.apache.commons.logging.Log;
080import org.apache.commons.logging.LogFactory;
081import org.kepler.authentication.AuthenticationException;
082import org.kepler.build.util.Version;
083import org.kepler.gui.ComponentLibraryTab;
084import org.kepler.gui.KeplerGraphFrame;
085import org.kepler.gui.KeplerGraphFrame.Components;
086import org.kepler.gui.KeplerGraphFrameUpdater;
087import org.kepler.gui.TabPane;
088import org.kepler.gui.TabPaneFactory;
089import org.kepler.gui.kar.ImportModuleDependenciesAction;
090import org.kepler.gui.lsid.LSIDViewer;
091import org.kepler.gui.state.StateChangeEvent;
092import org.kepler.gui.state.StateChangeMonitor;
093import org.kepler.kar.KARFile;
094import org.kepler.kar.ModuleDependencyUtil;
095import org.kepler.kar.SaveKAR;
096import org.kepler.kar.handlers.ProvKAREntryHandler;
097import org.kepler.objectmanager.cache.CacheException;
098import org.kepler.objectmanager.cache.CacheManager;
099import org.kepler.objectmanager.lsid.KeplerLSID;
100import org.kepler.objectmanager.repository.Repository;
101import org.kepler.objectmanager.repository.RepositoryManager;
102import org.kepler.provenance.ProvenanceEnabledListener;
103import org.kepler.provenance.ProvenanceRecorder;
104import org.kepler.provenance.QueryException;
105import org.kepler.provenance.Queryable;
106import org.kepler.provenance.RecordPlayer;
107import org.kepler.provenance.Recording;
108import org.kepler.provenance.RecordingException;
109import org.kepler.tagging.TaggingContext;
110import org.kepler.tagging.TaggingContextManager;
111import org.kepler.tagging.WindowIdentifier;
112import org.kepler.tagging.gui.TagBarInsertionUI;
113import org.kepler.tagging.gui.TagBarUI;
114import org.kepler.tagging.gui.TaggingPanel;
115import org.kepler.util.ProvenanceStore;
116import org.kepler.util.WorkflowRun;
117import org.kepler.workflowrunmanager.WRMDefaults;
118import org.kepler.workflowrunmanager.WorkflowRunManager;
119import org.kepler.workflowrunmanager.WorkflowRunManagerEvent;
120import org.kepler.workflowrunmanager.WorkflowRunManagerEventListener;
121import org.kepler.workflowrunmanager.WorkflowRunManagerManager;
122import org.kepler.workflowrunmanager.gui.kar.ExportRunsArchiveAction;
123
124import ptolemy.actor.CompositeActor;
125import ptolemy.actor.gui.PtolemyFrame;
126import ptolemy.actor.gui.TableauFrame;
127import ptolemy.kernel.ComponentEntity;
128import ptolemy.kernel.util.IllegalActionException;
129import ptolemy.kernel.util.NameDuplicationException;
130import ptolemy.kernel.util.NamedObj;
131import ptolemy.util.MessageHandler;
132import util.TableSorter;
133
134/**
135 * WorkflowRunManager TabPane
136 * 
137 * @author Derik Barseghian
138 * 
139 */
140public class WorkflowRunManagerPanel extends JPanel implements TabPane,
141                WorkflowRunManagerEventListener, ProvenanceEnabledListener, 
142                KeplerGraphFrameUpdater, ActionListener, PropertyChangeListener {
143
144        private static final Log log = LogFactory
145                        .getLog(WorkflowRunManagerPanel.class.getName());
146
147        private TableauFrame _frame;
148        private String _tabName;
149        // XXX for incomplete feature, hide/show columns:
150        // private boolean tempVisibleToggle = true;
151
152        private WRMDefaults wrmDefaults = WRMDefaults.getInstance();
153        
154        private WorkflowRunManagerTableModel wrmTableModel = null;
155        private JTable wrmjTable = null;
156        private TableSorter sorter = null;
157        private JPopupMenu popupMenu = new JPopupMenu();
158        private static final String OPEN_RUNS = "Open";
159        private static final String EXPORT_ARCHIVE = "Export Archive...";
160        private static final String UPLOAD_TO_REPOSITORY = "Upload to Repository...";
161        private static final String DELETE_RUN = "Delete";
162        private static final String CHANGE_COL_VISIBLE = "change colgroup visible test";
163        private static final String VIEW_RUN_LSID = "View Run LSID";
164        private static final String VIEW_WORKFLOW_LSID = "View Workflow LSID";
165        private static final String ENABLE_PROVENANCE = "Enable menu by turning on Provenance in toolbar";
166        private static final String RUNS_INCOMPAT_MOD_DEPS = "Runs have different module dependencies, can't archive together";
167        private static final String DOWNLOAD_KAR = "Download";
168        private static final String REFRESH = "Refresh";
169        private static final String SHOW_GRAPHICAL_ACTORS_OUTPUTS = "Show Graphical Actors Outputs";
170        
171    private JLabel unsupportedRecordingTypeMsg = new JLabel("Provenance RecordingType unsupported by Workflow Run Manager");
172        private JButton refreshButton = new JButton();
173        private boolean authenticate = ComponentLibraryTab.AUTHENTICATE;
174        
175        private JMenuItem openMenuItem = new JMenuItem(OPEN_RUNS);
176        private JMenuItem exportMenuItem = new JMenuItem(EXPORT_ARCHIVE);
177        private JMenuItem uploadMenuItem = new JMenuItem(UPLOAD_TO_REPOSITORY);
178        private JMenuItem deleteMenuItem = new JMenuItem(DELETE_RUN);
179        private JMenuItem viewRunLsidMenuItem = new JMenuItem(VIEW_RUN_LSID);
180        private JMenuItem viewWorkflowLSIDMenuItem = new JMenuItem(VIEW_WORKFLOW_LSID);
181        private JMenuItem provWarningMenuItem = new JMenuItem(ENABLE_PROVENANCE);
182        private JMenuItem changeColVisibleMenuItem = new JMenuItem(CHANGE_COL_VISIBLE);
183        private JMenuItem runsIncompatModDepsWarningMenuItem = new JMenuItem(RUNS_INCOMPAT_MOD_DEPS);
184        private JMenuItem downloadMenuItem = new JMenuItem(DOWNLOAD_KAR);
185        private JMenuItem showGraphicalActorsOutputsMenuItem = new JMenuItem(SHOW_GRAPHICAL_ACTORS_OUTPUTS);
186        
187        private static int doubleClick = 2;
188        // warn if user tries to open this many runs:
189        private static final int openWarningLimit = 10;
190
191        private NamedObj model = null;
192        
193        private int[] _lastSelectedRows = null;
194        
195        private boolean _isProvenanceEnabled = true;
196
197        private WorkflowRunManager workflowRunManager = null;
198
199        private KeplerGraphFrame kgf = null;
200
201        private boolean lastMouseEventWasPopupTrigger;
202        
203        private ExecIdCellEditor execIdHeaderCellEditor;
204        private DateCellEditor startTimeHeaderCellEditor;
205        private DurationCellEditor durationHeaderCellEditor;
206        private CellEditorListener cellEditorListener;
207
208        /*
209         * (non-Javadoc)
210         * 
211         * @see org.kepler.gui.TabPane#getParentFrame()
212         */
213        @Override
214    public TableauFrame getParentFrame() {
215                return _frame;
216        }
217
218        /*
219         * (non-Javadoc)
220         * 
221         * @see org.kepler.gui.TabPane#getTabName()
222         */
223        @Override
224    public String getTabName() {
225                return _tabName;
226        }
227
228        public void setTabName(String name) {
229                _tabName = name;
230        }
231
232        /*
233         * (non-Javadoc)
234         * 
235         * @see org.kepler.gui.TabPane#initializeTab()
236         */
237        @Override
238    public void initializeTab() throws Exception {
239                
240                this.removeAll();
241                this.repaint();
242                this.revalidate();
243                // Add components to the JPanel here.
244                this.setLayout(new BorderLayout());
245                
246                kgf = (KeplerGraphFrame) this._frame;
247                
248                resetProvenanceInfo(wrmDefaults.getDefaultProvenanceStore());
249
250                wrmTableModel = new WorkflowRunManagerTableModel(_frame);
251
252                // listen for WorkflowRunManagerEvents ourself too
253                workflowRunManager.addWorkflowRunManagerEventListener(this);
254
255                setupContextMenu();
256
257                sorter = new TableSorter(wrmTableModel);
258                wrmjTable = new JTable(sorter);
259                
260                wrmjTable.setColumnModel(new GroupableTableColumnModel());
261                GroupableTableColumnModel groupableTableColumnModel = (GroupableTableColumnModel) wrmjTable
262                                .getColumnModel();
263
264                sorter.setTableModel(wrmTableModel);
265
266                // Create search cell text fields, each with a focus listener. On
267                // focusLost, tell the header editingStopped.
268                // TODO this doesn't work yet for the custom cell editors (date,
269                // duration, execid..)
270                JTextField tagsTextField = new JTextField();
271                JTextField workflowTextField = new JTextField();
272                JTextField startTimeTextField = new JTextField();
273                JTextField durationTextField = new JTextField();
274                JTextField userTextField = new JTextField();
275                JTextField execIdTextField = new JTextField();
276
277                FocusListener headerTextFieldFocusListener = new FocusListener() {
278                        @Override
279            public void focusGained(FocusEvent e) {
280                        }
281
282                        @Override
283            public void focusLost(FocusEvent e) {
284                                GroupableTableHeader header = (GroupableTableHeader) wrmjTable
285                                                .getTableHeader();
286                                header.editingStopped(new ChangeEvent(this));
287                        }
288                };
289
290                tagsTextField.addFocusListener(headerTextFieldFocusListener);
291                workflowTextField.addFocusListener(headerTextFieldFocusListener);
292                startTimeTextField.addFocusListener(headerTextFieldFocusListener);
293                durationTextField.addFocusListener(headerTextFieldFocusListener);
294                userTextField.addFocusListener(headerTextFieldFocusListener);
295                execIdTextField.addFocusListener(headerTextFieldFocusListener);
296
297                DefaultCellEditor tagsHeaderCellEditor = new DefaultCellEditor(
298                                tagsTextField);
299                DefaultCellEditor workflowHeaderCellEditor = new DefaultCellEditor(
300                                workflowTextField);
301                startTimeHeaderCellEditor = new DateCellEditor(
302                                startTimeTextField);
303                durationHeaderCellEditor = new DurationCellEditor(
304                                durationTextField);
305                DefaultCellEditor userHeaderCellEditor = new DefaultCellEditor(
306                                userTextField);
307                execIdHeaderCellEditor = new ExecIdCellEditor(
308                                execIdTextField);
309
310                tagsHeaderCellEditor.setClickCountToStart(1);
311                workflowHeaderCellEditor.setClickCountToStart(1);
312                startTimeHeaderCellEditor.setClickCountToStart(1);
313                durationHeaderCellEditor.setClickCountToStart(1);
314                userHeaderCellEditor.setClickCountToStart(1);
315                execIdHeaderCellEditor.setClickCountToStart(1);
316
317                ColumnGroup tagsearchColumnGroup = new ColumnGroup(
318                                new GroupableTableCellRenderer(), tagsHeaderCellEditor,
319                                wrmDefaults.getDefault(WRMDefaults.TAGS));
320                tagsearchColumnGroup.add(groupableTableColumnModel.getColumn(wrmDefaults
321                                .getDefaultColIndex(WRMDefaults.TAGS)));
322                ColumnGroup workflowsearchColumnGroup = new ColumnGroup(
323                                new GroupableTableCellRenderer(), workflowHeaderCellEditor,
324                                wrmDefaults.getDefault(WRMDefaults.WORKFLOW_NAME));
325                workflowsearchColumnGroup.add(groupableTableColumnModel.getColumn(wrmDefaults
326                                .getDefaultColIndex(WRMDefaults.WORKFLOW_NAME)));
327                ColumnGroup startTimeSearchColumnGroup = new ColumnGroup(
328                                new GroupableTableCellRenderer(), startTimeHeaderCellEditor,
329                                wrmDefaults.getDefault(WRMDefaults.START_TIME));
330                startTimeSearchColumnGroup.add(groupableTableColumnModel.getColumn(wrmDefaults
331                                .getDefaultColIndex(WRMDefaults.START_TIME)));
332                ColumnGroup durationsearchColumnGroup = new ColumnGroup(
333                                new GroupableTableCellRenderer(), durationHeaderCellEditor,
334                                wrmDefaults.getDefault(WRMDefaults.DURATION));
335                durationsearchColumnGroup.add(groupableTableColumnModel.getColumn(wrmDefaults
336                                .getDefaultColIndex(WRMDefaults.DURATION)));
337                ColumnGroup usersearchColumnGroup = new ColumnGroup(
338                                new GroupableTableCellRenderer(), userHeaderCellEditor,
339                                wrmDefaults.getDefault(WRMDefaults.USER));
340                usersearchColumnGroup.add(groupableTableColumnModel.getColumn(wrmDefaults
341                                .getDefaultColIndex(WRMDefaults.USER)));
342                //ColumnGroup g_execIdsearch = new ColumnGroup(
343                //              new GroupableTableCellRenderer(), execIdHeaderCellEditor,
344                //              wrmDefaults.getDefault(WRMDefaults.EXEC_ID));
345                //g_execIdsearch.add(cm.getColumn(wrmDefaults
346                //              .getDefaultColIndex(WRMDefaults.EXEC_ID)));
347
348                groupableTableColumnModel.addColumnGroup(tagsearchColumnGroup);
349                groupableTableColumnModel.addColumnGroup(workflowsearchColumnGroup);
350                groupableTableColumnModel.addColumnGroup(startTimeSearchColumnGroup);
351                groupableTableColumnModel.addColumnGroup(durationsearchColumnGroup);
352                groupableTableColumnModel.addColumnGroup(usersearchColumnGroup);
353                //cm.addColumnGroup(g_execIdsearch);
354
355                // date column FormatRenderer
356                wrmjTable.getColumnModel().getColumn(
357                                wrmDefaults.getDefaultColIndex(WRMDefaults.START_TIME))
358                                .setCellRenderer(
359                                                new FormatRenderer(DateFormat.getDateTimeInstance()));
360                // duration column DurationCellRenderer
361                wrmjTable.getColumnModel().getColumn(
362                                wrmDefaults.getDefaultColIndex(WRMDefaults.DURATION))
363                                .setCellRenderer(new DurationCellRenderer());
364
365                // the other columns use WRMDefaultTableCellRenderer so they can also
366                // paint error rows red:
367                wrmjTable.getColumnModel().getColumn(
368                                wrmDefaults.getDefaultColIndex(WRMDefaults.TAGS))
369                                .setCellRenderer(new WRMDefaultTableCellRenderer());
370                wrmjTable.getColumnModel().getColumn(
371                                wrmDefaults.getDefaultColIndex(WRMDefaults.WORKFLOW_NAME))
372                                .setCellRenderer(new WRMDefaultTableCellRenderer());
373                wrmjTable.getColumnModel().getColumn(
374                                wrmDefaults.getDefaultColIndex(WRMDefaults.USER))
375                                .setCellRenderer(new WRMDefaultTableCellRenderer());
376                //wrmjTable.getColumnModel().getColumn(
377                //              wrmDefaults.getDefaultColIndex(WRMDefaults.EXEC_ID))
378                //              .setCellRenderer(new WRMDefaultTableCellRenderer());
379
380                // add mouse listener for context menu and to open selected runs on a
381                // double-click
382                wrmjTable.addMouseListener(new java.awt.event.MouseAdapter() {
383                        
384                        // os X
385                        @Override
386            public void mousePressed(java.awt.event.MouseEvent evt) {
387                                if ((evt.getClickCount() == doubleClick)
388                                                && !evt.isPopupTrigger()
389                                                && !lastMouseEventWasPopupTrigger
390                                                && _isProvenanceEnabled) {
391                                        // Disable double-click open since allows
392                                        // user to circumvent checking if runs have same mod deps,
393                                        // when in Strict (see how Open is disabled in the menu).
394                                        // Enabling would be easy, but some double-clicks would be 
395                                        // disallowed, which seems more confusing than it's worth.
396                                        //openMenuItem.doClick();
397                                } else {
398                                        if (_isProvenanceEnabled){
399                                                setTagContextToCurrentlySelectedRows();
400                                        }
401                                        jTableShowContextMenu(evt);
402                                }
403                                lastMouseEventWasPopupTrigger = evt.isPopupTrigger();
404                        }
405
406                        // Windows
407                        @Override
408            public void mouseReleased(java.awt.event.MouseEvent evt) {
409                                if ((evt.getClickCount() == doubleClick)
410                                                && !evt.isPopupTrigger()
411                                                && !lastMouseEventWasPopupTrigger
412                                                && _isProvenanceEnabled) {
413                                } else {
414                                        jTableShowContextMenu(evt);
415                                }
416                                lastMouseEventWasPopupTrigger = evt.isPopupTrigger();
417                        }
418                });
419
420                wrmjTable.getColumnModel().getColumn(
421                                wrmDefaults.getDefaultColIndex(WRMDefaults.TAGS))
422                                .setHeaderValue(WRMDefaults.TAGS);
423                wrmjTable.getColumnModel().getColumn(
424                                wrmDefaults.getDefaultColIndex(WRMDefaults.WORKFLOW_NAME))
425                                .setHeaderValue(WRMDefaults.WORKFLOW_NAME);
426                wrmjTable.getColumnModel().getColumn(
427                                wrmDefaults.getDefaultColIndex(WRMDefaults.START_TIME))
428                                .setHeaderValue(WRMDefaults.START_TIME);
429                wrmjTable.getColumnModel().getColumn(
430                                wrmDefaults.getDefaultColIndex(WRMDefaults.DURATION))
431                                .setHeaderValue(WRMDefaults.DURATION);
432                wrmjTable.getColumnModel().getColumn(
433                                wrmDefaults.getDefaultColIndex(WRMDefaults.USER))
434                                .setHeaderValue(WRMDefaults.USER);
435                //wrmjTable.getColumnModel().getColumn(
436                //              wrmDefaults.getDefaultColIndex(WRMDefaults.EXEC_ID))
437                //              .setHeaderValue(WRMDefaults.EXEC_ID);
438
439                // Set some column widths to be wide enough
440                wrmjTable.getColumnModel().getColumn(
441                                wrmDefaults.getDefaultColIndex(WRMDefaults.TAGS))
442                                .setPreferredWidth(WRMDefaults.TAGS_COLUMN_WIDTH);
443                wrmjTable.getColumnModel().getColumn(
444                                wrmDefaults.getDefaultColIndex(WRMDefaults.WORKFLOW_NAME))
445                                .setPreferredWidth(WRMDefaults.WORKFLOW_NAME_COLUMN_WIDTH);
446                wrmjTable.getColumnModel().getColumn(
447                                wrmDefaults.getDefaultColIndex(WRMDefaults.START_TIME))
448                                .setPreferredWidth(WRMDefaults.START_TIME_COLUMN_WIDTH);
449                wrmjTable.getColumnModel().getColumn(
450                                wrmDefaults.getDefaultColIndex(WRMDefaults.DURATION))
451                                .setPreferredWidth(WRMDefaults.DURATION_COLUMN_WIDTH);
452                wrmjTable.getColumnModel().getColumn(
453                                wrmDefaults.getDefaultColIndex(WRMDefaults.USER))
454                                .setPreferredWidth(WRMDefaults.USER_NAME_COLUMN_WIDTH);
455                //wrmjTable.getColumnModel().getColumn(
456                //              wrmDefaults.getDefaultColIndex(WRMDefaults.EXEC_ID))
457                //              .setPreferredWidth(WRMDefaults.EXEC_ID_COLUMN_WIDTH);
458
459                // Set some GUI properties of table to improve appearance:
460                wrmjTable.getColumnModel().setColumnMargin(WRMDefaults.COLUMN_MARGIN);
461                wrmjTable.setGridColor(WRMDefaults.TABLE_GRID_COLOR);
462                wrmjTable.setShowHorizontalLines(WRMDefaults.SHOW_HORIZONTAL_LINES);
463                wrmjTable.setShowVerticalLines(WRMDefaults.SHOW_VERTICAL_LINES);
464                wrmjTable.setRowHeight(WRMDefaults.WRM_ROW_HEIGHT);
465                wrmjTable.setFont(WRMDefaults.WRM_FONT);
466
467                wrmjTable.setTableHeader(new GroupableTableHeader(
468                                (GroupableTableColumnModel) wrmjTable.getColumnModel()));
469                sorter.setTableHeader(wrmjTable.getTableHeader());
470
471                // CellEditorListen on all header cells, on any editingStopped doSearch.
472                cellEditorListener = new CellEditorListener() {
473                        @Override
474            public void editingCanceled(ChangeEvent e) {
475                        }
476
477                        @Override
478            public void editingStopped(ChangeEvent e) {
479                                // System.out.println("editing stopped, calling WorkflowRunManagerPanel filterRuns()");
480                                filterRuns();
481                        }
482                };
483
484                GroupableTableHeader header = (GroupableTableHeader) wrmjTable
485                                .getTableHeader();
486                TableCellEditor tmpTableCellEditor = null;
487                for (int i = 0; i < wrmDefaults.getColumnCount(); i++) {
488                        tmpTableCellEditor = header.getCellEditor(i);
489                        if (tmpTableCellEditor != null) {
490                                tmpTableCellEditor.addCellEditorListener(cellEditorListener);
491                        } else {
492                                log.error("header cell editor is null");
493                        }
494                }
495
496                // try to populate by default, if another window hasn't already done so
497                if (workflowRunManager.getWorkflowRuns().isEmpty()) {
498                        queryForAllRuns();
499                } else {
500                        filterRuns();
501                }
502
503                // clean up the listener when the frame closes
504                final KeplerGraphFrameUpdater keplerGraphFrameUpdater = this;
505                final WorkflowRunManagerEventListener eventlistener = this;
506                _frame.addWindowListener(new WindowAdapter() {
507                        @Override
508            public void windowClosed(WindowEvent e) {
509                                execIdHeaderCellEditor.dispose();
510                                durationHeaderCellEditor.dispose();
511                                startTimeHeaderCellEditor.dispose();
512                                workflowRunManager.dispose(eventlistener);
513                                KeplerGraphFrame.removeUpdater(keplerGraphFrameUpdater);
514
515                                GroupableTableHeader header = (GroupableTableHeader) wrmjTable
516                                .getTableHeader();
517                                TableCellEditor tmpTableCellEditor = null;
518                                for (int i = 0; i < wrmDefaults.getColumnCount(); i++) {
519                                        tmpTableCellEditor = header.getCellEditor(i);
520                                        if (tmpTableCellEditor != null) {
521                                                tmpTableCellEditor.removeCellEditorListener(cellEditorListener);
522                                        } else {
523                                                log.error("header cell editor is null");
524                                        }
525                                }
526                        }
527                });
528                
529                
530                // doesn't seem to help:
531                // wrmjTable.putClientProperty("terminateEditOnFocusLost",
532                // Boolean.TRUE);
533
534                JScrollPane _workflowRunManagerPane = new JScrollPane(wrmjTable);
535                
536                refreshButton.setText("Refresh");
537                refreshButton.setActionCommand(REFRESH);
538                refreshButton.addActionListener(this);
539                refreshButton.setSize(180, 25);
540                refreshButton.setEnabled(false);
541                
542                
543                FlowLayout flowLayout = new FlowLayout(FlowLayout.RIGHT);
544                JPanel upperPanel = new JPanel(flowLayout);
545            JComboBox provenanceStoresComboBox = new JComboBox(wrmDefaults.getProvenanceStores());
546            provenanceStoresComboBox.setRenderer(new ComboBoxRenderer());
547            ComboBoxAction comboBoxAction = new ComboBoxAction();
548            provenanceStoresComboBox.addActionListener(comboBoxAction);
549
550                if (workflowRunManager.usingSupportedRecordingType()){
551                        unsupportedRecordingTypeMsg.setVisible(false);
552                }
553                else{
554                        unsupportedRecordingTypeMsg.setVisible(true);
555                }
556            upperPanel.add(unsupportedRecordingTypeMsg);
557            upperPanel.add(refreshButton);
558            upperPanel.add(provenanceStoresComboBox);
559                
560                // TODO: I like not having setMinimumSize, so I or Kepler can
561                // arbitrarily resize but this is a stopgap to partially deal w/ 
562                // the "getting stuck" bug. Note settings for _eastSplitPane in 
563                // DefaultViewPane.initializeView() when attempting to debug this.
564                _workflowRunManagerPane.setMinimumSize(new Dimension(
565                                WRMDefaults.WRM_PANE_WIDTH, WRMDefaults.WRM_PANE_HEIGHT));
566
567                _workflowRunManagerPane.setPreferredSize(new Dimension(
568                                WRMDefaults.WRM_PANE_WIDTH, WRMDefaults.WRM_PANE_HEIGHT));
569                this.add(upperPanel, BorderLayout.NORTH);
570                this.add(_workflowRunManagerPane);
571                this.revalidate();
572
573                // sort by startTime DESCENDING by default
574                sorter.setSortingStatus(wrmDefaults
575                                .getDefaultColIndex(WRMDefaults.START_TIME),
576                                TableSorter.DESCENDING);
577
578                // restrict area in which clicking will cause sort to occur (currently
579                // the bottom half of header):
580                int heightRestriction = ((GroupableTableHeaderUI) header.getUI())
581                                .getCGroupHeight();
582                sorter.setSortableHeightRestriction(heightRestriction);
583
584                wrmjTable.getSelectionModel().addListSelectionListener(
585                                _listSelectionListener);
586
587                // System.out.println("wrmjTable.getAutoCreateColumnsFromModel():"
588                // +wrmjTable.getAutoCreateColumnsFromModel());
589                
590                KeplerGraphFrame.addUpdater(this);
591        }
592
593        // used for tagging
594        private static class ComponentFinder<T> {
595                public ComponentFinder(Component[] componentsArray, Class<T> cls) {
596                        for (Component comp : componentsArray) {
597                                try {
598                                        component = cls.cast(comp);
599                                        match = true;
600                                } catch (ClassCastException ignored) {
601                                }
602                        }
603                }
604
605                public boolean matchFound() {
606                        return match;
607                }
608
609                public T getComponent() {
610                        return component;
611                }
612
613                private boolean match = false;
614                private T component;
615        }
616
617        // used for tagging
618        private int getWindowId() {
619                try {
620                        JToolBar toolbar = kgf.getToolBar();
621                        if (toolbar == null){
622                                log.error("WorkflowRunManagerPanel.getWindowId() toolbar == null");
623                                return -1;
624                        }
625                        
626                        ComponentFinder<TaggingPanel> finder1 = new ComponentFinder<TaggingPanel>(
627                                        toolbar.getComponents(), TaggingPanel.class);
628                        if (!finder1.matchFound()) {
629                                log.error("TaggingPanel not found in toolbar");
630                                return -1;
631                        }
632                        ComponentFinder<TagBarInsertionUI> finder2 = new ComponentFinder<TagBarInsertionUI>(
633                                        finder1.getComponent().getComponents(),
634                                        TagBarInsertionUI.class);
635                        int id = finder2.getComponent().getId();
636                        return id;
637                } catch (ClassCastException ex) {
638                        log.error("The frame is not a KeplerGraphFrame, it's an "
639                                        + this._frame.getClass().getCanonicalName());
640                }
641                return -1;
642        }
643
644        /*
645         * (non-Javadoc)
646         * 
647         * @see
648         * org.kepler.gui.TabPane#setParentFrame(ptolemy.actor.gui.TableauFrame)
649         */
650        @Override
651    public void setParentFrame(TableauFrame parent) {
652                _frame = parent;
653        }
654
655        /**
656         * A factory that creates a TabPane.
657         * 
658         *@author Aaron Schultz
659         */
660        public static class Factory extends TabPaneFactory {
661                /**
662                 * Create a factory with the given name and container.
663                 * 
664                 *@param container
665                 *            The container.
666                 *@param name
667                 *            The name of the entity.
668                 *@exception IllegalActionException
669                 *                If the container is incompatible with this attribute.
670                 *@exception NameDuplicationException
671                 *                If the name coincides with an attribute already in the
672                 *                container.
673                 */
674                public Factory(NamedObj container, String name)
675                                throws IllegalActionException, NameDuplicationException {
676                        super(container, name);
677                }
678
679                /**
680                 * Create a library pane that displays the given library of actors.
681                 * 
682                 * @return A new LibraryPaneTab that displays the library
683                 */
684                @Override
685        public TabPane createTabPane(TableauFrame parent) {
686                        WorkflowRunManagerPanel wrmp = new WorkflowRunManagerPanel();
687
688                        /*
689                         * Optionally you can create a method called setTabName and use the
690                         * "name" value from the configuration.xml file by calling
691                         * this.getName(). For Example if you have <property
692                         * name="randomTestTab"
693                         * class="org.kepler.gui.TabPaneExtensionExample$Factory" /> in
694                         * configuration.xml then the name of the tab in the GUI becomes
695                         * randomTestTab
696                         */
697                        wrmp.setTabName(this.getName());
698                        return wrmp;
699                }
700        }
701
702        /**
703         * Query provenance for all runs.
704         * This clears and sets in-memory runs.
705         * @throws AuthenticationException 
706         */
707        private void queryForAllRuns() throws AuthenticationException {
708                
709                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
710                String percent_wildcard = "%";
711
712                if (!workflowRunManager.isConnected()) {
713                        log.debug("WorkflowRunManagerPanel queryForAllRuns !workflowRunManager.isConnected() call reconnect()");
714                        reconnect();
715                }
716                if (workflowRunManager.isConnected()) {
717                        log.debug("WorkflowRunManagerPanel queryForAllRuns workflowRunManager.isConnected() call wrmTableModel.updateDataUsingWRMQuery()");
718                        wrmTableModel.updateDataUsingWRMQuery(percent_wildcard,
719                                        percent_wildcard, percent_wildcard,
720                                        percent_wildcard, percent_wildcard, percent_wildcard, authenticate);
721                }
722                
723                setCursor(Cursor.getDefaultCursor());
724        }
725        
726
727        private void clearAllRuns() {
728                ArrayList<WorkflowRun> emptyRuns = new ArrayList<WorkflowRun>();
729                workflowRunManager.setWorkflowRuns(emptyRuns);
730                wrmTableModel.clearAllRuns();
731        }
732
733        /**
734         * Filter all in memory runs for a particular WorkflowRunManager and 
735         * update WRM table model with results.
736         */
737        private void filterRuns() {
738
739                String tagsSearchString = getSearchString(WRMDefaults.TAGS);
740                String wfNameSearchString = getSearchString(WRMDefaults.WORKFLOW_NAME);
741                String startTimeSearchString = getSearchString(WRMDefaults.START_TIME);
742                String durationSearchString = getSearchString(WRMDefaults.DURATION);
743                String userSearchString = getSearchString(WRMDefaults.USER);
744                //String execIdSearchString = getSearchString(WRMDefaults.EXEC_ID);
745                String execIdSearchString = "%";
746                
747                wrmTableModel.filterRuns(wfNameSearchString, userSearchString,
748                                startTimeSearchString, durationSearchString,
749                                execIdSearchString, tagsSearchString);
750        }
751
752        /**
753         * Return user entered search string for soughtColumnName
754         * 
755         * @param soughtColumnName
756         * @return
757         */
758        private String getSearchString(String soughtColumnName) {
759
760                int modelColumnIndex = 0;
761                String searchString = "%";
762                try {
763                        modelColumnIndex = wrmDefaults.getDefaultColIndex(soughtColumnName);
764                } catch (Exception e) {
765                        // TODO Auto-generated catch block
766                        e.printStackTrace();
767                }
768                int viewColIndex = wrmjTable.convertColumnIndexToView(modelColumnIndex);
769
770                GroupableTableColumnModel gtColumnModel = (GroupableTableColumnModel) wrmjTable
771                                .getColumnModel();
772                ColumnGroup cGroup = gtColumnModel.getColumnGroup(viewColIndex);
773
774                if (cGroup == null || !cGroup.isVisible()) {
775                        return searchString;
776                }
777
778                TableColumn aColumn = gtColumnModel.getColumn(viewColIndex);
779
780                Iterator<ColumnGroup> iter = gtColumnModel.getColumnGroups(aColumn);
781
782                //FIXME should really fetch a precise cGroup, not last:
783                if (iter != null) {
784                        while (iter.hasNext()) {
785                                cGroup = iter.next();
786                                searchString = cGroup.getHeaderValue().toString();
787                        }
788                }
789                if (searchString.equals(wrmDefaults
790                                .getDefaultSearchStringForColIndex(modelColumnIndex))) {
791                        searchString = "%";
792                }
793                if (searchString.equals("")) {
794                        searchString = "%";
795                }
796
797                return searchString;
798        }
799        
800        /**
801         * TODO, sometimes the change shows in the gui, othertimes it doesn't.
802         * 
803         * Manually set a column's search string
804         * @param soughtColumnName
805         * @param searchString
806         */
807        private void setSearchStringAndFilter(String soughtColumnName, String searchString) {
808                
809                int modelColumnIndex = 0;
810                try {
811                        modelColumnIndex = wrmDefaults.getDefaultColIndex(soughtColumnName);
812                } catch (Exception e) {
813                        // TODO Auto-generated catch block
814                        e.printStackTrace();
815                }
816                int viewColIndex = wrmjTable.convertColumnIndexToView(modelColumnIndex);
817
818                GroupableTableColumnModel gtColumnModel = (GroupableTableColumnModel) wrmjTable
819                                .getColumnModel();
820                ColumnGroup cGroup = gtColumnModel.getColumnGroup(viewColIndex);
821
822                if (cGroup == null || !cGroup.isVisible()) {
823                        return;
824                }
825
826                TableColumn column = gtColumnModel.getColumn(viewColIndex);
827                Iterator<ColumnGroup> iter = gtColumnModel.getColumnGroups(column);
828
829                //FIXME should really fetch a precise cGroup, not last:
830                if (iter != null) {
831                        while (iter.hasNext()) {
832                                cGroup = iter.next();
833                        }
834                }
835                cGroup.setHeaderValue(searchString);
836                
837                //now filter the runs.
838                filterRuns();
839        }
840
841
842        /**
843         * Given a list of execution LSIDS, open them. Creates a temp KAR and then
844         * uses KARFile.openKARContents to open it.
845         * 
846         * @param runLSIDs
847         * @throws QueryException
848         */
849        private void openRuns(List<KeplerLSID> runLSIDs) throws QueryException {
850
851                // export run(s) for selected row(s)
852                try {
853
854                        ArrayList<WorkflowRun> workflowRuns = wrmTableModel
855                                .getWorkflowRunsForRows(getSorterSelectedRows());
856                        
857                        WorkflowRun wr = workflowRuns.get(0);
858                        String runsModDeps = wr.getModuleDependencies();
859                        
860                        SaveKAR saveKAR = createTempKAR(runLSIDs, runsModDeps);
861
862                        KARFile karf = new KARFile(saveKAR.getFile());
863                        karf.openKARContents(_frame, false);
864                        karf.close();
865                        
866                        // immediately delete it, so user gets Save As... dialog
867                        // instead of Save (since we don't show file path in title, they
868                        // won't know they're saving it to temp file location). 
869                        saveKAR.getFile().delete();
870
871                        // now clear any runs added to the "selected" list
872                        // in prep for any subsequent saves
873                        workflowRunManager.clearSelectedRuns();
874                        
875                        // TODO this is too bold, if openKAR doesn't open a wf,
876                        // and this is the only window open, kepler quits!
877                        // check if this is last window. Also should probably
878                        // only do this if it's the first default blank window.
879                        // if (!kgf.isModified()) {
880                        // kgf.close();
881                        // }
882
883                } catch (CacheException e) {
884                        // TODO Auto-generated catch block
885                        e.printStackTrace();
886                } catch (Exception e) {
887                        // TODO Auto-generated catch block
888                        e.printStackTrace();
889                }
890        }
891
892        
893        /**
894         * Warning: this method clears and sets WorkflowRunManager selectedRuns
895         * you will almost definitely want to call wrm.clearSelectedRuns soon
896         * after calling this method.
897         * @param runLSIDs
898         * @return
899         */
900        private SaveKAR createTempKAR(List<KeplerLSID> runLSIDs, String overrideModDeps){
901                
902                //ObjectManager om = ObjectManager.getInstance();
903                CacheManager cman = null;
904                try {
905                        cman = CacheManager.getInstance();
906                } catch (CacheException e) {
907                        // TODO Auto-generated catch block
908                        e.printStackTrace();
909                }
910
911                SaveKAR savekar = new SaveKAR();
912
913                File tmpKARPath = cman.getTempFile();
914                savekar.setFile(tmpKARPath);
915                
916                // first clear any runs previously added to the "selected" list:
917                workflowRunManager.clearSelectedRuns();
918                
919                Iterator<KeplerLSID> runLsidItr = runLSIDs.iterator();
920                while (runLsidItr.hasNext()){
921                        KeplerLSID runLSID = runLsidItr.next();
922                        try {
923                                ComponentEntity<?> workflow = workflowRunManager.getAssociatedWorkflowForWorkflowRun(runLSID);
924                                if (workflow != null) {
925                                        
926                                        // Here we store the Run LSID in the Workflow Run Manager Singleton
927                                        // so the WorkflowRunEntryHandler can figure out which runs for which
928                                        // workflows to save
929                                        workflowRunManager.addRunToSelectedRuns(runLSID);
930                                        
931                                        // Here we add the workflow the run is associated with as an initiator
932                                        // of the SaveKAR
933                                        savekar.addSaveInitiator(workflow);
934                                }
935                        } catch (Exception exc) {
936                                exc.printStackTrace();
937                        }
938                }
939                
940                // turn off saving PROV to the KAR since we won't use
941                // to open the the run.
942                final boolean saveValue = ProvKAREntryHandler.setSave(false);
943                try {
944                    savekar.saveToDisk(_frame, overrideModDeps);
945                } finally {
946                    // restore the previous save value.
947                    ProvKAREntryHandler.setSave(saveValue);
948                }
949                return savekar;
950        }
951
952
953        private void resetProvenanceInfo(ProvenanceStore provenanceStore) {
954
955                if (provenanceStore == null){
956                        log.error("WorkflowRunManagerPanel resetProvenanceInfo provenanceStore == null!");
957                }
958                else{
959                        // remove listener from old workflowRunManager list, add to new
960                        if(workflowRunManager !=null){
961                                workflowRunManager.removeWorkflowRunManagerEventListener(this);
962                        }
963                        
964                        WorkflowRunManagerManager wrmm = WorkflowRunManagerManager.getInstance();
965                        workflowRunManager = wrmm.getWRM(_frame, provenanceStore);
966                        workflowRunManager.addWorkflowRunManagerEventListener(this);
967
968                        if (!workflowRunManager.isConnected()){
969                                reconnect();
970                        }
971                        
972                        ProvenanceRecorder pr = workflowRunManager.getProvenanceRecorder();
973                        if (pr != null){
974                                pr.removeEnabledListener(this);
975                                pr.addEnabledListener(this);
976                        }
977                }
978        }
979
980        /**
981         * Reconnect workflowRunManager to provenance store.
982         */
983        private void reconnect() {
984
985                if (workflowRunManager.isConnected()) {
986                        try {
987                                workflowRunManager.disconnect();
988                        } catch (IllegalActionException e) {
989                                log.error("Unable to disconnect from provenance store." + e.getMessage());
990                                return;
991                        } catch (QueryException e) {
992                                log.error("Unable to disconnect from provenance store." + e.getMessage());
993                                return;
994                        }
995                }
996
997                workflowRunManager.connect();
998                
999                if (workflowRunManager.usingSupportedRecordingType()){
1000                        unsupportedRecordingTypeMsg.setVisible(false);
1001                }
1002                else{
1003                        unsupportedRecordingTypeMsg.setVisible(true);
1004                }
1005                
1006                if (!workflowRunManager.isConnected()) {        
1007                        log.error("WorkflowRunManagerPanel reconnect() unable to connect.");
1008                        return;
1009                }
1010
1011        }
1012        
1013
1014        /**
1015         * get KeplerLSIDs of workflowRuns for rows
1016         * 
1017         * @param rows
1018         * @return KeplerLSIDs associated with rows
1019         */
1020        private List<KeplerLSID> getWorkflowRunLSIDsForRows(int[] rows) {
1021
1022                ArrayList<KeplerLSID> lsids = new ArrayList<KeplerLSID>();
1023                ArrayList<WorkflowRun> workflowRuns = wrmTableModel
1024                                .getWorkflowRunsForRows(rows);
1025                ListIterator<WorkflowRun> wfRunItr = workflowRuns.listIterator();
1026                while (wfRunItr.hasNext()) {
1027                        lsids.add(wfRunItr.next().getExecLSID());
1028                }
1029
1030                return lsids;
1031        }
1032
1033        /**
1034         * anonymous class to handle list selection events
1035         */
1036        private ListSelectionListener _listSelectionListener = new ListSelectionListener() {
1037
1038                @Override
1039        public void valueChanged(ListSelectionEvent e) {
1040
1041                        // no need to do this during multiple events
1042                        if (!e.getValueIsAdjusting()) {
1043
1044                                if (getSorterSelectedRows().length == 1 && _isProvenanceEnabled) {
1045                                        int sortedRow = getSorterSelectedRows()[0];
1046                                        WorkflowRun selectedRun = wrmTableModel
1047                                                        .getWorkflowRunForRow(sortedRow);
1048                                        StateChangeEvent stateEvent = new StateChangeEvent(kgf,
1049                                                        WorkflowRun.WORKFLOWRUN_SELECTED, selectedRun);
1050                                        StateChangeMonitor.getInstance().notifyStateChange(
1051                                                        stateEvent);
1052                                }
1053                                
1054                        }
1055                }
1056        };
1057
1058        /**
1059         * Set the tagging target to WorkflowRun and set the objects we're tagging to the
1060         * currently selected rows (skipping preview runs).
1061         */
1062        private synchronized void setTagContextToCurrentlySelectedRows() {
1063                // Set the tagging indicator to a workflow run
1064                WindowIdentifier windowIdentifier = new WindowIdentifier("test"
1065                                + getWindowId(), kgf);
1066                TaggingContextManager.getInstance(windowIdentifier).setTaggingContext(
1067                                TaggingContext.WORKFLOW_RUN);
1068
1069                // Set the object we're currently tagging.
1070                // Load the new tags from that target
1071                Collection<WorkflowRun> workflowRuns = wrmTableModel
1072                                .getWorkflowRunsForRows(getSorterSelectedRows());
1073                _lastSelectedRows = getSorterSelectedRows();
1074                Collection<NamedObj> nos = new ArrayList<NamedObj>();
1075
1076                for (WorkflowRun run: workflowRuns) {
1077                        if (!run.getType().equals(WorkflowRun.type.Preview.toString())&&
1078                                        !run.getType().equals(WorkflowRun.type.Preview_Error.toString())){
1079                                nos.add(run);
1080                        }
1081                }
1082                TaggingContextManager.getInstance(windowIdentifier).setTagTarget(nos);
1083        }
1084        
1085        /**
1086         * Set the tagging target to WorkflowRun and set the objects we're tagging to the
1087         * currently selected rows.
1088         */
1089        private synchronized void setTagContextToRows(int[] rows) {
1090                                
1091                // Set the tagging indicator to a workflow run
1092                WindowIdentifier windowIdentifier = new WindowIdentifier("test"
1093                                + getWindowId(), kgf);
1094                TaggingContextManager.getInstance(windowIdentifier).setTaggingContext(
1095                                TaggingContext.WORKFLOW_RUN);
1096
1097                // Set the object we're currently tagging.
1098                // Load the new tags from that target
1099                Collection<WorkflowRun> workflowRuns = wrmTableModel
1100                                .getWorkflowRunsForRows(rows);
1101                Collection<NamedObj> nos = new ArrayList<NamedObj>();
1102
1103                Iterator<WorkflowRun> itr = workflowRuns.iterator();
1104                while (itr.hasNext()) {
1105                        nos.add(itr.next());
1106                }
1107                TaggingContextManager.getInstance(windowIdentifier).setTagTarget(nos);
1108        }
1109
1110        private synchronized void setTagContextToWorkflow(){
1111                // Change the tagging indicator to the workflow
1112                WindowIdentifier windowIdentifier = new WindowIdentifier(
1113                                "test" + getWindowId(), kgf);
1114                TaggingContextManager.getInstance(windowIdentifier)
1115                                .setTaggingContext(TaggingContext.WORKFLOW);
1116                if (model == null){
1117                        return;
1118                }
1119                if (model.toplevel() == null){
1120                        return;
1121                }
1122                
1123                CompositeActor toplevel = (CompositeActor) model.toplevel();
1124                TaggingContextManager.getInstance(windowIdentifier)
1125                                .setTagTarget(toplevel,
1126                                                TaggingContextManager.getInstance(
1127                                                                windowIdentifier)
1128                                                                .getTagBarInsertionUI()
1129                                                                .getExistingTagsPanel());
1130        }
1131        
1132        
1133        @Override
1134    public void actionPerformed(ActionEvent e) {
1135                
1136                setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1137
1138                if (e.getActionCommand().equals(OPEN_RUNS)) {
1139                        // open run(s) for selected row(s)
1140                        int openResponse = 0;
1141                        try {
1142                                List<KeplerLSID> rowLsids = getWorkflowRunLSIDsForRows(getSorterSelectedRows());
1143                                if (rowLsids.size() > openWarningLimit) {
1144                                        openResponse = JOptionPane.showConfirmDialog(_frame,
1145                                                        "Do you really want to open " + rowLsids.size()
1146                                                                        + " runs?", "Open many runs?",
1147                                                        JOptionPane.YES_NO_OPTION);
1148                                        if (openResponse == JOptionPane.NO_OPTION) {
1149                                                return;
1150                                        }
1151                                }
1152
1153                                // String currentModDeps =
1154                                // ModuleDependencyUtil.buildModuleDependenciesString();
1155
1156                                // determine module dependencies of selected runs. In order to
1157                                // get here, all runs should have same mod deps, so just use 
1158                                // the first's
1159                                ArrayList<WorkflowRun> workflowRuns = wrmTableModel
1160                                                .getWorkflowRunsForRows(getSorterSelectedRows());
1161                                WorkflowRun wr = workflowRuns.get(0);
1162                                String runModDepsStr = wr.getModuleDependencies();
1163                                Vector<String> runModDeps = ModuleDependencyUtil
1164                                                .parseDependencyString(runModDepsStr);
1165
1166                                if (!ModuleDependencyUtil
1167                                                .checkIfModuleDependenciesSatisfied(runModDeps)) {
1168                                        log.debug("run module dependencies are NOT satisfied, calling ImportModuleDependenciesAction...");
1169
1170                                        // module-dependencies aren't satisfied, invoke
1171                                        // ImportModuleDependenciesAction
1172                                        ImportModuleDependenciesAction imda = new ImportModuleDependenciesAction(
1173                                                        _frame);
1174                                        
1175                                        List<KeplerLSID> runLSIDs = getWorkflowRunLSIDsForRows(getSorterSelectedRows());
1176                                        SaveKAR saveKAR = createTempKAR(runLSIDs, runModDepsStr);
1177                                        
1178                                        imda.setArchiveFile(saveKAR.getFile());
1179                                        imda.updateHistoryAndLastDirectory(false);
1180                                        imda.setDependencies(runModDeps);
1181                                        imda.actionPerformed(e);
1182
1183                                        // now clear any runs added to the "selected" list
1184                                        // in prep for any subsequent saves
1185                                        workflowRunManager.clearSelectedRuns();
1186                                } else {
1187                                        log.debug("run module dependencies are satisfied, calling openRuns...");
1188                                        openRuns(getWorkflowRunLSIDsForRows(getSorterSelectedRows()));
1189                                }
1190                                
1191                        } catch (QueryException e1) {
1192                                // TODO Auto-generated catch block
1193                                e1.printStackTrace();
1194                        }
1195
1196                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1197
1198                } else if (e.getActionCommand().equals(EXPORT_ARCHIVE)
1199                                || e.getActionCommand().equals(UPLOAD_TO_REPOSITORY)) {
1200                        // export and possibly upload runs for selected row(s).
1201
1202                        List<KeplerLSID> runRowLSIDs = getWorkflowRunLSIDsForRows(getSorterSelectedRows());
1203
1204                        // determine module dependencies of selected runs. In order to get
1205                        // here, all runs should have same mod deps, so just use the first's
1206                        ArrayList<WorkflowRun> workflowRuns = wrmTableModel
1207                                        .getWorkflowRunsForRows(getSorterSelectedRows());
1208                        WorkflowRun wr = workflowRuns.get(0);
1209                        String runModDepsStr = wr.getModuleDependencies();
1210                        Vector<String> runModDeps = ModuleDependencyUtil
1211                                        .parseDependencyString(runModDepsStr);
1212
1213                        if (!ModuleDependencyUtil
1214                                        .checkIfModuleDependenciesSatisfied(runModDeps)) {
1215                                // module-dependencies aren't satisfied, invoke
1216                                // ImportModuleDependenciesAction
1217                                ImportModuleDependenciesAction imda = new ImportModuleDependenciesAction(
1218                                                _frame);
1219
1220                                List<KeplerLSID> runLSIDs = getWorkflowRunLSIDsForRows(getSorterSelectedRows());
1221                                SaveKAR saveKAR = createTempKAR(runLSIDs, runModDepsStr);
1222                                
1223                                imda.setExportMode(true);
1224                                imda.updateHistoryAndLastDirectory(false);
1225                                imda.setArchiveFile(saveKAR.getFile());
1226                                imda.setDependencies(runModDeps);
1227                                imda.actionPerformed(e);
1228                                if (imda.getNeedToDoAForceExport()){
1229                                        // since a force export can fail to include artifacts from inactive modules
1230                                        // do not override the module dependency list, 
1231                                        ExportRunsArchiveAction eraa = new ExportRunsArchiveAction(
1232                                                        getParentFrame(), runRowLSIDs, null);
1233                                        if (e.getActionCommand().equals(EXPORT_ARCHIVE)) {
1234                                                eraa.setUpload(false);
1235                                        } else if (e.getActionCommand().equals(UPLOAD_TO_REPOSITORY)) {
1236                                                try {
1237                                                        RepositoryManager repoManager = RepositoryManager
1238                                                                        .getInstance();
1239                                                        Repository saveRepository = repoManager
1240                                                                        .getSaveRepository();
1241                                                        if (saveRepository == null) {
1242                                                                // MessageHandler.error("To upload to a remote repository, select one from the "
1243                                                                // + "component search preferences");
1244                                                                JOptionPane.showMessageDialog(_frame,
1245                                                                                "To upload to a remote repository, select one from the "
1246                                                                                                + "component search preferences",
1247                                                                                "Cannot Save", JOptionPane.ERROR_MESSAGE);
1248                                                                return;
1249                                                        }
1250                                                } catch (IOException e1) {
1251                                                        // TODO Auto-generated catch block
1252                                                        e1.printStackTrace();
1253                                                } catch (Exception e1) {
1254                                                        // TODO Auto-generated catch block
1255                                                        e1.printStackTrace();
1256                                                }
1257
1258                                        }
1259                                        eraa.actionPerformed(e);
1260                                }
1261
1262                                // now clear any runs added to the "selected" list
1263                                // in prep for any subsequent saves
1264                                workflowRunManager.clearSelectedRuns();
1265                        } else {
1266                        
1267                                ExportRunsArchiveAction eraa = new ExportRunsArchiveAction(
1268                                                getParentFrame(), runRowLSIDs, runModDepsStr);
1269                                if (e.getActionCommand().equals(EXPORT_ARCHIVE)) {
1270                                        eraa.setUpload(false);
1271                                } else if (e.getActionCommand().equals(UPLOAD_TO_REPOSITORY)) {
1272                                        try {
1273                                                RepositoryManager repoManager = RepositoryManager
1274                                                                .getInstance();
1275                                                Repository saveRepository = repoManager
1276                                                                .getSaveRepository();
1277                                                if (saveRepository == null) {
1278                                                        // MessageHandler.error("To upload to a remote repository, select one from the "
1279                                                        // + "component search preferences");
1280                                                        JOptionPane.showMessageDialog(_frame,
1281                                                                        "To upload to a remote repository, select one from the "
1282                                                                                        + "component search preferences",
1283                                                                        "Cannot Save", JOptionPane.ERROR_MESSAGE);
1284                                                        return;
1285                                                }
1286                                        } catch (IOException e1) {
1287                                                // TODO Auto-generated catch block
1288                                                e1.printStackTrace();
1289                                        } catch (Exception e1) {
1290                                                // TODO Auto-generated catch block
1291                                                e1.printStackTrace();
1292                                        }
1293
1294                                }
1295                                eraa.actionPerformed(e);
1296                                
1297                                // now clear any runs added to the "selected" list
1298                                // in prep for any subsequent saves
1299                                workflowRunManager.clearSelectedRuns();
1300                        }
1301                        
1302                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1303
1304                } else if (e.getActionCommand().equals(DELETE_RUN)) {
1305                        // delete run(s) for selected row(s)
1306
1307                        int deleteResponse = 0;
1308
1309                        if (isIncompleteRunSelected()) {
1310                                deleteResponse = JOptionPane
1311                                                .showConfirmDialog(
1312                                                                _frame,
1313                                                                "WARNING! An incomplete run is selected, deleting "
1314                                                                                + "a run that is still executing\n may corrupt your provenance store, "
1315                                                                                + "are you sure you would like to proceed?",
1316                                                                "WARNING Possible corruption!", JOptionPane.YES_NO_OPTION);
1317                        } else if (getSorterSelectedRows().length == 1) {
1318                                deleteResponse = JOptionPane.showConfirmDialog(_frame,
1319                                                "Do you want to delete "
1320                                                                + getSorterSelectedRows().length + " run?",
1321                                                "Delete runs?", JOptionPane.YES_NO_OPTION);
1322                        } else {
1323                                deleteResponse = JOptionPane.showConfirmDialog(_frame,
1324                                                "Do you want to delete "
1325                                                                + getSorterSelectedRows().length + " runs?",
1326                                                "Delete runs?", JOptionPane.YES_NO_OPTION);
1327                        }
1328                        if (deleteResponse == JOptionPane.YES_OPTION) {
1329                                ProvenanceRecorder pr = workflowRunManager
1330                                                .getProvenanceRecorder();
1331                                Recording recording = pr.getRecording();
1332
1333                                List<KeplerLSID> runsToDelete = getWorkflowRunLSIDsForRows(getSorterSelectedRows());
1334                                if (!runsToDelete.isEmpty()) {
1335                                        
1336                                        DeleteRunsSwingWorker drsw = new DeleteRunsSwingWorker(
1337                                                        recording, runsToDelete, authenticate);
1338                                        drsw.execute();
1339                                        drsw.addPropertyChangeListener(this);
1340
1341                                } else {
1342                                        log.error("WorkflowRunManagerPanel " +
1343                                                        "_actionListener ERROR, no runs to delete!");
1344                                        setCursor(Cursor.getDefaultCursor());
1345                                }
1346
1347                                setTagContextToWorkflow();
1348                        }else{
1349                                setCursor(Cursor.getDefaultCursor());
1350                        }
1351
1352                } else if (e.getActionCommand().equals(VIEW_RUN_LSID)) {
1353
1354                        int[] rows = getSorterSelectedRows();
1355                        if (rows.length == 1) {
1356                                List<KeplerLSID> rowLsids = getWorkflowRunLSIDsForRows(rows);
1357                                KeplerLSID lsid = rowLsids.get(0);
1358                                try {
1359                                        WorkflowRun wr = workflowRunManager.getRun(lsid
1360                                                        .toStringWithoutRevision());
1361                                        if (wr != null) {
1362
1363                                                LSIDViewer lv = new LSIDViewer();
1364                                                lv.setEditingEnabled(false);
1365                                                lv.initialize(wr);
1366                                                lv.setSize(new Dimension(400, 300));
1367                                                lv.setLocationRelativeTo(_frame);
1368                                                lv.setVisible(true);
1369                                        }
1370                                } catch (Exception exc) {
1371                                        exc.printStackTrace();
1372                                }
1373                        }
1374                        
1375                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1376
1377                } else if (e.getActionCommand().equals(VIEW_WORKFLOW_LSID)) {
1378
1379                        int[] rows = getSorterSelectedRows();
1380                        if (rows.length == 1) {
1381
1382                                List<KeplerLSID> rowLsids = getWorkflowRunLSIDsForRows(rows);
1383                                KeplerLSID runLSID = rowLsids.get(0);
1384                                try {
1385                                        ComponentEntity<?> workflow = workflowRunManager
1386                                                        .getAssociatedWorkflowForWorkflowRun(runLSID);
1387                                        if (workflow != null) {
1388                                                LSIDViewer lv = new LSIDViewer();
1389                                                lv.setEditingEnabled(false);
1390                                                lv.initialize(workflow);
1391                                                lv.setSize(new Dimension(400, 300));
1392                                                lv.setLocationRelativeTo(_frame);
1393                                                lv.setVisible(true);
1394                                        }
1395                                } catch (Exception exc) {
1396                                        exc.printStackTrace();
1397                                }
1398                        }
1399                        
1400                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1401                        
1402                } else if (e.getActionCommand().equals(DOWNLOAD_KAR)) {
1403
1404                        ArrayList<WorkflowRun> selectedRuns = wrmTableModel
1405                                        .getWorkflowRunsForRows(getSorterSelectedRows());
1406                        ArrayList<KeplerLSID> failedDownloads = new ArrayList<KeplerLSID>();
1407                        for (WorkflowRun run : selectedRuns) {
1408                                // only attempt to download preview runs.
1409                                if (run.getType().equals(WorkflowRun.type.Preview.toString())
1410                                                || run.getType().equals(
1411                                                                WorkflowRun.type.Preview_Error.toString())) {
1412                                        boolean downloadSuccess = false;
1413                                        try {
1414                                                downloadSuccess = workflowRunManager.downloadRunKAR(
1415                                                                run.getExecLSID(), authenticate);
1416                                        } catch (AuthenticationException e1) {
1417                                                // TODO Auto-generated catch block
1418                                                e1.printStackTrace();
1419                                        }
1420                                        if (!downloadSuccess) {
1421                                                failedDownloads.add(run.getExecLSID());
1422                                        }
1423                                }
1424                        }
1425                        if (!failedDownloads.isEmpty()) {
1426                                JOptionPane.showMessageDialog(_frame,
1427                                                "" + failedDownloads.size()
1428                                                                + " KAR(s) failed to download.",
1429                                                "Download Error", JOptionPane.ERROR_MESSAGE);
1430                        }
1431                        
1432                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1433                        
1434                } else if (e.getActionCommand().equals(REFRESH)) {
1435                        // set runs
1436                        try {
1437                                queryForAllRuns();
1438                                filterRuns();
1439                        } catch (AuthenticationException e1) {
1440                                // TODO Auto-generated catch block
1441                                e1.printStackTrace();
1442                        }
1443                        
1444                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1445                        
1446                } else if (e.getActionCommand().equals(CHANGE_COL_VISIBLE)) {
1447                        // TODO under construction and not currently used.
1448
1449                        // FIXME hardcode etc, temp test to toggle a col
1450                        // visible/invisible
1451                        /*
1452                         * try {
1453                         * 
1454                         * int startTimeColumn; startTimeColumn = wrmjTable
1455                         * .convertColumnIndexToView(wrmDefaults
1456                         * .getDefaultColIndex(WRMDefaults.START_TIME));
1457                         * System.out.println("trying to toggle colgroup:" + startTimeColumn
1458                         * + " visibility");
1459                         * 
1460                         * GroupableTableColumnModel cm = (GroupableTableColumnModel)
1461                         * wrmjTable .getColumnModel(); if (tempVisibleToggle == true) {
1462                         * tempVisibleToggle = false; } else { tempVisibleToggle = true; }
1463                         * 
1464                         * if (tempVisibleToggle) { // set it visible in default location cm
1465                         * .setColumnGroupVisible( wrmDefaults
1466                         * .getDefaultColIndex(WRMDefaults.START_TIME), cm
1467                         * .getColumnGroup(wrmDefaults
1468                         * .getDefaultColIndex(WRMDefaults.START_TIME)), tempVisibleToggle);
1469                         * } else { // remove it from current location
1470                         * cm.setColumnGroupVisible(startTimeColumn, cm
1471                         * .getColumnGroup(startTimeColumn), tempVisibleToggle); }
1472                         * 
1473                         * if (tempVisibleToggle) {
1474                         * 
1475                         * wrmjTable .getColumnModel() .getColumn( wrmDefaults
1476                         * .getDefaultColIndex(WRMDefaults.START_TIME)) .setCellRenderer(
1477                         * new WRMDefaultTableCellRenderer()); wrmjTable .getColumnModel()
1478                         * .getColumn( wrmDefaults
1479                         * .getDefaultColIndex(WRMDefaults.START_TIME))
1480                         * .setHeaderValue(WRMDefaults.START_TIME);
1481                         * 
1482                         * // wrmjTable.setTableHeader(new //
1483                         * GroupableTableHeader((GroupableTableColumnModel
1484                         * )wrmjTable.getColumnModel())); //
1485                         * sorter.setTableHeader(wrmjTable.getTableHeader()); }
1486                         * 
1487                         * // refresh table so search string of hidden column which // went
1488                         * // away goes into effect // /queryDBforRuns(); } catch (Exception
1489                         * e1) { // TODO Auto-generated catch block e1.printStackTrace(); }
1490                         */
1491                        
1492                        //setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1493                } else if (e.getActionCommand().equals(SHOW_GRAPHICAL_ACTORS_OUTPUTS)) {
1494                    
1495                    try {
1496                    // FIXME copied from OPEN_RUNS
1497                    
1498                // open run(s) for selected row(s)
1499                int openResponse = 0;
1500                List<KeplerLSID> rowLsids = getWorkflowRunLSIDsForRows(getSorterSelectedRows());
1501                if (rowLsids.size() > openWarningLimit) {
1502                    openResponse = JOptionPane.showConfirmDialog(_frame,
1503                            "Do you really want to show outputs for " + rowLsids.size()
1504                                    + " runs?", "Show many runs?",
1505                            JOptionPane.YES_NO_OPTION);
1506                    if (openResponse == JOptionPane.NO_OPTION) {
1507                        return;
1508                    }
1509                }
1510                
1511                ArrayList<WorkflowRun> workflowRuns = wrmTableModel
1512                        .getWorkflowRunsForRows(getSorterSelectedRows());
1513                
1514                Queryable queryable = workflowRunManager.getQueryable();
1515    
1516                for(WorkflowRun run : workflowRuns) {
1517                    String runModDepsStr = run.getModuleDependencies();
1518                    Vector<String> runModDeps = ModuleDependencyUtil
1519                            .parseDependencyString(runModDepsStr);
1520    
1521                    if (!ModuleDependencyUtil
1522                            .checkIfModuleDependenciesSatisfied(runModDeps)) {
1523                        StringBuilder buf = new StringBuilder("Current Kepler suite " +
1524                            "does not include modules used in run:\n");
1525                        for(Map.Entry<String, Version> entry : 
1526                            ModuleDependencyUtil.getUnsatisfiedDependencies(runModDeps).entrySet()) {
1527                            String versionStr;
1528                            Version version = entry.getValue();
1529                            if(version == null) {
1530                                versionStr = "svn trunk";
1531                            } else {
1532                                versionStr = version.getVersionString();
1533                            }
1534                            buf.append(entry.getKey())
1535                                .append(" ")
1536                                .append(versionStr)
1537                                .append("\n");
1538                        }
1539                        buf.append("Try to show graphical actor outputs anyway?");
1540                        if(!MessageHandler.yesNoQuestion(buf.toString())) {
1541                            continue;
1542                        }
1543                    }
1544                        
1545                    Integer execId = null;
1546                    try {
1547                        execId = queryable.getExecutionForExecutionLSID(run.getExecLSID());
1548                    } catch (QueryException ex) {
1549                        MessageHandler.error("Error querying execution id for run.", ex);
1550                        continue;
1551                    }
1552                    
1553                    if(execId == null) {
1554                        MessageHandler.error("Could not get execution id for run.");
1555                        continue;
1556                    }
1557                    
1558                    RecordPlayer player = new RecordPlayer(queryable, null);
1559                    player.setExecuteGraphicalActors(true);
1560                    try {
1561                        player.play(execId);
1562                    } catch (QueryException | RecordingException ex) {
1563                        MessageHandler.error("Error replaying run.", ex);
1564                        continue;
1565                    }
1566                }
1567                    } finally {            
1568                        setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
1569                    }
1570
1571                }
1572        }
1573        
1574
1575        /**
1576         * Show WRM context menu if mouseEvent.isPopupTrigger
1577         */
1578        private void jTableShowContextMenu(java.awt.event.MouseEvent mouseEvent) {
1579
1580                if (mouseEvent.isPopupTrigger() || mouseEvent.isControlDown()) {
1581                        int row = wrmjTable.rowAtPoint(mouseEvent.getPoint());
1582                        int sorterRow = sorter.modelIndex(row);
1583                        int[] sorterSelectedRows = getSorterSelectedRows();
1584
1585                        if (sorterRow != -1) {
1586
1587                                boolean clickWasOnASelectedRow = false;
1588                                for (int i = 0; i < sorterSelectedRows.length; i++) {
1589                                        if (sorterRow == sorterSelectedRows[i]) {
1590                                                clickWasOnASelectedRow = true;
1591                                                break;
1592                                        }
1593                                }
1594                                if (!clickWasOnASelectedRow) {
1595                                        wrmjTable.setRowSelectionInterval(row, row);
1596                                        sorterSelectedRows = getSorterSelectedRows();
1597                                }
1598
1599                                // only show the context menu if at least one row
1600                                // is selected.
1601                                if (sorterSelectedRows.length > 0) {
1602                                        
1603                                        if (_isProvenanceEnabled) {
1604                                                
1605                                                popupMenu.removeAll();
1606                                                
1607                                                if (isPreviewRunSelected()) {
1608                                                        popupMenu.add(downloadMenuItem);
1609                                                        popupMenu.add(viewRunLsidMenuItem);
1610                                                        downloadMenuItem.setEnabled(true);
1611                                                        viewRunLsidMenuItem.setEnabled(true);
1612                                                        if (sorterSelectedRows.length > 1) {
1613                                                                viewRunLsidMenuItem.setEnabled(false);
1614                                                        }
1615                                                } else {
1616                                                        popupMenu.add(openMenuItem);
1617                                                        popupMenu.addSeparator();
1618                                                        popupMenu.add(showGraphicalActorsOutputsMenuItem);
1619                            popupMenu.addSeparator();
1620                                                        popupMenu.add(exportMenuItem);
1621                                                        popupMenu.add(uploadMenuItem);
1622                                                        popupMenu.add(viewRunLsidMenuItem);
1623                                                        popupMenu.add(viewWorkflowLSIDMenuItem);
1624                                                        popupMenu.addSeparator();
1625                                                        popupMenu.add(deleteMenuItem);
1626                                                        //popupMenu.add(changeColVisibleMenuItem);
1627        
1628                                                        openMenuItem.setEnabled(true);
1629                                                        exportMenuItem.setEnabled(true);
1630                                                        uploadMenuItem.setEnabled(true);
1631                                                        deleteMenuItem.setEnabled(true);
1632                                                        viewRunLsidMenuItem.setEnabled(true);
1633                                                        viewWorkflowLSIDMenuItem.setEnabled(true);
1634        
1635                                                        // disallow export, upload, open (any kar creation)
1636                                                        // of kars with multiple runs. see bug#5175
1637                                                        if (sorterSelectedRows.length > 1) {
1638                                                                openMenuItem.setEnabled(false);
1639                                                                exportMenuItem.setEnabled(false);
1640                                                                uploadMenuItem.setEnabled(false);
1641                                                                viewRunLsidMenuItem.setEnabled(false);
1642                                                                viewWorkflowLSIDMenuItem.setEnabled(false);
1643                                                        }
1644                                                        
1645                                                        // disallow export and upload when an 
1646                                                        // incomplete run is selected
1647                                                        if (isIncompleteRunSelected()){
1648                                                                exportMenuItem.setEnabled(false);
1649                                                                uploadMenuItem.setEnabled(false);
1650                                                        }
1651        
1652                                                        // disallow open, export and upload when runs have incompatible
1653                                                        // module dependencies (since kar's mod deps get set to run(s')
1654                                                        // mod deps)
1655                                                        if (areRunsWithIncompatibleModuleDependenciesSelected()) {
1656                                                                openMenuItem.setEnabled(false);
1657                                                                exportMenuItem.setEnabled(false);
1658                                                                uploadMenuItem.setEnabled(false);
1659                                                                
1660                                                                ///TODO once bug#5175 is fixed, this warning becomes relevant again.
1661                                                                // until then it doesn't make sense to show.
1662                                                                ///popupMenu.addSeparator();
1663                                                                ///popupMenu.add(runsIncompatModDepsWarningMenuItem);
1664                                                                ///runsIncompatModDepsWarningMenuItem.setEnabled(false);
1665                                                        }
1666                                                }
1667
1668                                                popupMenu.show(mouseEvent.getComponent(), mouseEvent
1669                                                                .getX(), mouseEvent.getY());
1670                                        } else {
1671                                                popupMenu.removeAll();
1672                                                popupMenu.add(provWarningMenuItem);
1673                                                provWarningMenuItem.setEnabled(false);
1674
1675                                                popupMenu.show(mouseEvent.getComponent(), mouseEvent
1676                                                                .getX(), mouseEvent.getY());
1677                                        }
1678                                }
1679                        }
1680                }
1681        }
1682        
1683
1684        /**
1685         * Return the TableSorter selected rows translated from the table selected
1686         * rows.
1687         * 
1688         * @return sorterSelectedRows
1689         */
1690        private int[] getSorterSelectedRows() {
1691                int[] selectedRows = wrmjTable.getSelectedRows();
1692                // initialize to the proper length
1693                int[] sorterSelectedRows = selectedRows; 
1694
1695                for (int i = 0; i < selectedRows.length; i++) {
1696                        sorterSelectedRows[i] = sorter.modelIndex(selectedRows[i]);
1697                }
1698                return sorterSelectedRows;
1699        }
1700
1701
1702        private boolean isPreviewRunSelected(){         
1703                
1704                int[] sorterSelectedRows = getSorterSelectedRows();
1705                
1706                if (sorterSelectedRows.length > 0) {
1707                        for (int i=0; i<sorterSelectedRows.length; i++){
1708                                WorkflowRun selectedRun = wrmTableModel
1709                                        .getWorkflowRunForRow(sorterSelectedRows[i]);
1710                                
1711                                if (selectedRun.getType().equals(WorkflowRun.type.Preview.toString())
1712                                        || selectedRun.getType().equals(WorkflowRun.type.Preview_Error.toString())){
1713                                        return true;
1714                                }
1715                        }
1716                }
1717                return false;
1718        }
1719        
1720        private boolean isIncompleteRunSelected(){
1721        
1722                int[] sorterSelectedRows = getSorterSelectedRows();
1723
1724                if (sorterSelectedRows.length > 0) {
1725                        for (int i=0; i<sorterSelectedRows.length; i++){
1726                                WorkflowRun selectedRun = wrmTableModel
1727                                        .getWorkflowRunForRow(sorterSelectedRows[i]);
1728                                
1729                                if (selectedRun.getDuration() < 0){
1730                                        return true;
1731                                }
1732                        }
1733                }
1734                return false;
1735        }
1736        
1737        private boolean areRunsWithIncompatibleModuleDependenciesSelected(){
1738                
1739                int[] sorterSelectedRows = getSorterSelectedRows();
1740
1741                if (sorterSelectedRows.length > 1) {
1742                        
1743                        String run0ModDeps = null;
1744                        String runXModDeps = null;
1745                        for (int i=0; i<sorterSelectedRows.length; i++){
1746                                WorkflowRun selectedRun = wrmTableModel
1747                                        .getWorkflowRunForRow(sorterSelectedRows[i]);
1748
1749                                if (i == 0){
1750                                        run0ModDeps = selectedRun.getModuleDependencies();
1751                                }
1752                                runXModDeps = selectedRun.getModuleDependencies();
1753                                if (runXModDeps == null){
1754                                        log.error("WorkflowRunManagerPanel jTableShowContextMenu runXModDeps == null ");
1755                                }
1756                                if (run0ModDeps == null){
1757                                        log.error("WorkflowRunManagerPanel jTableShowContextMenu run0ModDeps == null ");
1758                                }
1759                                if (!runXModDeps.equals(run0ModDeps)){
1760                                        return true;
1761                                }
1762                        }
1763                }
1764                return false;
1765        }
1766        
1767        
1768        /**
1769         * Setup the WRM context menu.
1770         */
1771        private void setupContextMenu() {
1772
1773                openMenuItem.removeActionListener(this);
1774                openMenuItem.addActionListener(this);
1775                openMenuItem.setActionCommand(OPEN_RUNS);
1776                exportMenuItem.removeActionListener(this);
1777                exportMenuItem.addActionListener(this);
1778                exportMenuItem.setActionCommand(EXPORT_ARCHIVE);
1779                uploadMenuItem.removeActionListener(this);
1780                uploadMenuItem.addActionListener(this);
1781                uploadMenuItem.setActionCommand(UPLOAD_TO_REPOSITORY);
1782                deleteMenuItem.removeActionListener(this);
1783                deleteMenuItem.addActionListener(this);
1784                deleteMenuItem.setActionCommand(DELETE_RUN);
1785                changeColVisibleMenuItem.removeActionListener(this);
1786                changeColVisibleMenuItem.addActionListener(this);
1787                changeColVisibleMenuItem.setActionCommand(CHANGE_COL_VISIBLE);
1788                viewRunLsidMenuItem.removeActionListener(this);
1789                viewRunLsidMenuItem.addActionListener(this);
1790                viewRunLsidMenuItem.setActionCommand(VIEW_RUN_LSID);
1791                viewWorkflowLSIDMenuItem.removeActionListener(this);
1792                viewWorkflowLSIDMenuItem.addActionListener(this);
1793                viewWorkflowLSIDMenuItem.setActionCommand(VIEW_WORKFLOW_LSID);
1794                downloadMenuItem.removeActionListener(this);
1795                downloadMenuItem.addActionListener(this);
1796                downloadMenuItem.setActionCommand(DOWNLOAD_KAR);
1797                showGraphicalActorsOutputsMenuItem.removeActionListener(this);
1798                showGraphicalActorsOutputsMenuItem.addActionListener(this);
1799                showGraphicalActorsOutputsMenuItem.setActionCommand(SHOW_GRAPHICAL_ACTORS_OUTPUTS);
1800
1801                popupMenu.add(openMenuItem);
1802                popupMenu.addSeparator();
1803                popupMenu.add(showGraphicalActorsOutputsMenuItem);
1804                popupMenu.addSeparator();
1805                popupMenu.add(exportMenuItem);
1806                popupMenu.add(uploadMenuItem);
1807                popupMenu.add(viewRunLsidMenuItem);
1808                popupMenu.add(viewWorkflowLSIDMenuItem);
1809                popupMenu.addSeparator();
1810                popupMenu.add(deleteMenuItem);
1811                // popupMenu.add(changeColVisibleMenuItem);
1812                
1813                
1814                Font currentFont = runsIncompatModDepsWarningMenuItem.getFont();
1815                Font italicFont = new Font(currentFont.getName(), Font.ITALIC, currentFont.getSize());
1816                runsIncompatModDepsWarningMenuItem.setFont(italicFont);
1817        }
1818
1819
1820        @Override
1821    public void workflowRunManagerEventOccurred(WorkflowRunManagerEvent evt) {
1822                
1823                if (evt.getEventName().equals(WorkflowRunManagerEvent.PROGRAMATIC_FILTER)){
1824                        HashMap<String,String> columnsAndFilters = (HashMap<String, String>) evt.getEventData();
1825                        Iterator<String> itr = columnsAndFilters.keySet().iterator();
1826                        while (itr.hasNext()){
1827                                String columnName = itr.next();
1828                                String columnFilter = columnsAndFilters.get(columnName);
1829                                log.debug("WorkflowRunManagerPanel workflowRunManagerEventOccurred PROGRAMATIC_FILTER calling setSearchStringAndFilter("+columnName+","+columnFilter+")");
1830                                setSearchStringAndFilter(columnName, columnFilter);
1831                        }
1832                }
1833                else{
1834                        filterRuns();
1835                }
1836                
1837                /*
1838                 Iterator<KeplerLSID> lsidItr = evt.getEventLSIDs().iterator();
1839                 while (lsidItr.hasNext()){
1840                        KeplerLSID lsid = lsidItr.next();
1841                        WorkflowRun run = workflowRunManager.getWorkflowRuns().get(lsid.toStringWithoutRevision());
1842                        if (run != null){
1843                                System.out.println("run with lsid: " + lsid + " has execId:"+ run.getExecId());
1844                        }
1845                }
1846                */
1847                
1848                // since run execLSIDs now change revision on tag events, this is here to 
1849                // ensure tagging context stays up to date with the latest WorkflowRun objects
1850                if (evt.getEventName().equals(WorkflowRunManagerEvent.TAG_ADDED) ||
1851                                evt.getEventName().equals(WorkflowRunManagerEvent.TAG_REMOVED)){
1852                        if (_lastSelectedRows != null && wrmjTable.getRowCount() > 0 
1853                                        && evt.isLastEvent() && _isProvenanceEnabled){
1854                                setTagContextToRows(_lastSelectedRows);
1855                        }
1856                }
1857                
1858        }
1859
1860        /*
1861         * (non-Javadoc)
1862         * @see org.kepler.provenance.ProvenanceEnabledListener#toggle(boolean)
1863         */
1864        @Override
1865    public void toggle(boolean enabled) {
1866                _isProvenanceEnabled = enabled;
1867                if (!_isProvenanceEnabled){
1868                        setTagContextToWorkflow();
1869                }
1870        }
1871
1872        @Override
1873    public void updateFrameComponents(Components components) {
1874        //KeplerGraphFrame frame = components.getFrame();
1875
1876                model = ((PtolemyFrame) _frame).getModel();
1877                ProvenanceRecorder pr = ProvenanceRecorder.getDefaultProvenanceRecorder(model);
1878                
1879                if (pr != null){
1880                        pr.removeEnabledListener(this);
1881                        pr.addEnabledListener(this);
1882                }
1883        }
1884        
1885        @Override
1886    public void dispose(KeplerGraphFrame frame) {
1887
1888        }
1889
1890        @Override
1891    public int compareTo(KeplerGraphFrameUpdater o) {
1892                if (this == o)
1893                        return 0;
1894                else
1895                        //must be greater than provenance
1896                        return 1;
1897        }
1898
1899        
1900
1901        private static class ComboBoxRenderer extends JLabel implements ListCellRenderer {
1902
1903                public ComboBoxRenderer() {
1904                        setOpaque(true);
1905                }
1906
1907                @Override
1908        public Component getListCellRendererComponent(JList list, Object value,
1909                                int index, boolean isSelected, boolean cellHasFocus) {
1910                        if (isSelected) {
1911                                setBackground(list.getSelectionBackground());
1912                                setForeground(list.getSelectionForeground());
1913                        } else {
1914                                setBackground(list.getBackground());
1915                                setForeground(list.getForeground());
1916                        }
1917                        
1918                        ProvenanceStore provenanceStore = (ProvenanceStore) value;
1919                        if (provenanceStore != null) {
1920                                setText(provenanceStore.getName());
1921                        }
1922
1923                        return this;
1924                }
1925                
1926        }
1927        
1928
1929        /**
1930         * ComboBox for choosing a different provenance store
1931         * for this Workflow Run Manager.
1932         */
1933        private class ComboBoxAction implements ActionListener {
1934
1935            Object oldItem;
1936            
1937                @Override
1938        public void actionPerformed(ActionEvent e) {
1939                                                
1940                        final JComboBox cb = (JComboBox) e.getSource();
1941                        Object newItem = cb.getSelectedItem();
1942                        boolean same = newItem.equals(oldItem);
1943                oldItem = newItem;
1944                
1945                //no need to update if same store selected again
1946                        if (!same) {
1947                                        Executors.newSingleThreadExecutor().execute(new Runnable() {
1948                                                @Override
1949                        public void run() {
1950                                                        try {
1951                                                                changeProvenanceStore(cb);
1952                                                        } catch (Exception e) {
1953                                                                // TODO Auto-generated catch block
1954                                                                e.printStackTrace();
1955                                                        }
1956                                                }
1957                                        });
1958                }
1959                }
1960
1961                private void changeProvenanceStore(JComboBox cb){
1962                        
1963                        WorkflowRunManagerPanel wrmPanel = (WorkflowRunManagerPanel) cb
1964                                        .getParent().getParent();
1965                        wrmPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
1966
1967                        ProvenanceStore selectedProvStore = (ProvenanceStore) cb
1968                                        .getSelectedItem();
1969
1970                        synchronized (selectedProvStore) {
1971
1972                                resetProvenanceInfo(selectedProvStore);
1973
1974                                // clear out the old while fetching new runs
1975                                // this must be after resetProvenanceInfo, so it occurs on the
1976                                // right WRM
1977                                clearAllRuns();
1978
1979                                if (selectedProvStore.isRemoteKarStore()) {
1980                                        refreshButton.setEnabled(true);
1981                                } else {
1982                                        refreshButton.setEnabled(false);
1983                                }
1984
1985                                // TODO is this really the appropriate place to reset
1986                                // tagEventListener?
1987                                WindowIdentifier windowIdentifier = new WindowIdentifier("test"
1988                                                + getWindowId(), kgf);
1989                                ProvenanceRecorder pr = workflowRunManager
1990                                                .getProvenanceRecorder();
1991                                TagBarUI tagBarUI = TaggingContextManager
1992                                                .getInstance(windowIdentifier).getTagBarInsertionUI()
1993                                                .getTagBarUI();
1994                                tagBarUI.removeTagEventListener(pr);
1995
1996                                // WorkflowRunManagerManager.getInstance().printDebug();
1997                                // set runs
1998                                try {
1999                                        queryForAllRuns();
2000                                } catch (AuthenticationException e) {
2001                                        // TODO Auto-generated catch block
2002                                        e.printStackTrace();
2003                                }
2004                                filterRuns();
2005
2006                                // TODO is this really the appropriate place to reset
2007                                // tagEventListener?
2008                                pr = workflowRunManager.getProvenanceRecorder();
2009                                tagBarUI.addTagEventListener(pr);
2010
2011                        }
2012
2013                        wrmPanel.setCursor(Cursor.getDefaultCursor());
2014                }
2015                
2016        }
2017        
2018        private class DeleteRunsSwingWorker extends SwingWorker<Integer, Void> {
2019
2020                private Recording _recording = null;
2021                private List<KeplerLSID> _runsToDelete = null;
2022                private boolean _authenticate = false;
2023                
2024                public DeleteRunsSwingWorker(Recording recording, 
2025                                List<KeplerLSID>runsToDelete, boolean authenticate){
2026                        _recording = recording;
2027                        _runsToDelete = runsToDelete;
2028                        _authenticate = authenticate;
2029                }
2030
2031                @Override
2032        protected Integer doInBackground() throws Exception {
2033                        return workflowRunManager.deleteRuns(_recording, _runsToDelete,
2034                                        _authenticate);
2035                }
2036
2037                @Override
2038        protected void done() {
2039                        //if (isCancelled()){
2040                }
2041
2042        }
2043
2044        @Override
2045    public void propertyChange(PropertyChangeEvent evt) {
2046                if (evt.getNewValue().equals(
2047                                SwingWorker.StateValue.STARTED)) {
2048                        setCursor(Cursor
2049                                        .getPredefinedCursor(Cursor.WAIT_CURSOR));
2050                }else if (evt.getNewValue().equals(
2051                                SwingWorker.StateValue.DONE)){
2052                        setCursor(Cursor.getDefaultCursor());
2053                }
2054        }
2055        
2056}
2057
2058