001/*
002 * Copyright (c) 2015 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2015-11-02 19:59:42 +0000 (Mon, 02 Nov 2015) $' 
007 * '$Revision: 34197 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029package org.kepler.profiling.gui;
030
031import java.util.concurrent.ExecutorService;
032import java.util.concurrent.Executors;
033
034import org.kepler.gui.TabPane;
035import org.kepler.gui.TabPaneFactory;
036import org.kepler.gui.state.StateChangeEvent;
037import org.kepler.gui.state.StateChangeListener;
038import org.kepler.gui.state.StateChangeMonitor;
039import org.kepler.provenance.ProvenanceRecorder;
040import org.kepler.provenance.Queryable;
041import org.kepler.provenance.RecordPlayer;
042import org.kepler.util.WorkflowRun;
043import org.kepler.workflowrunmanager.WorkflowRunManager;
044import org.kepler.workflowrunmanager.WorkflowRunManagerManager;
045
046import ptolemy.actor.gui.TableauFrame;
047import ptolemy.kernel.util.IllegalActionException;
048import ptolemy.kernel.util.NameDuplicationException;
049import ptolemy.kernel.util.NamedObj;
050import ptolemy.util.MessageHandler;
051
052/** A panel that displays actor execution information for the currently
053 *  selected workflow in the Workflow Run Manager.
054 *  
055 *  @author Daniel Crawl
056 *  @version $Id: PreviousExecutionPanel.java 34197 2015-11-02 19:59:42Z crawl $
057 * 
058 */
059public class PreviousExecutionPanel extends ExecutionMonitorPanel
060    implements StateChangeListener {
061
062    /** Create a new PreviousExecutionPanel with the specified name. */
063    public PreviousExecutionPanel(String name) {
064        super(name);
065        
066        _useCurrentTimeForElapsed = false;
067    }
068
069    /** React to a state change. */
070    @Override
071    public void handleStateChange(StateChangeEvent event) {
072        
073        super.handleStateChange(event);
074        
075        // see if the event is a workflow being selected in the 
076        // workflow run manager and originates in our frame.
077        if(event.getChangedState().equals(WorkflowRun.WORKFLOWRUN_SELECTED) &&
078                event.getSource() == getParentFrame() &&
079                _viewIsSelected) {            
080            NamedObj namedObj = event.getReference();
081            if (namedObj instanceof WorkflowRun) {
082                WorkflowRun wfRun = (WorkflowRun) namedObj;
083                _execId = wfRun.getExecId();
084                
085                Queryable queryable = _workflowRunManager.getQueryable();
086                if(queryable == null) {
087                    MessageHandler.error("Could not find query interface for workflow.");
088                    return;
089                }
090                
091                ProvenanceRecorder recorder = _executionMonitorRecording.getContainer();
092                if(recorder != null) {
093                    recorder.removePiggyback(_executionMonitorRecording);
094                }
095                
096                // replay the execution provenance to update the execution
097                // monitor table.
098                _player = new RecordPlayer(queryable, _executionMonitorRecording);
099                _player.setPlayPortEvents(false);
100                _replay();
101            }
102        }                       
103    }
104
105    /** Initialize the tab. */
106    @Override
107    public void initializeTab() throws Exception {
108
109        super.initializeTab();
110        
111        _executionMonitorRecording = new ExecutionMonitorRecording();
112
113        _statusLabel.setText("Select row in Workflow Run Manager to see execution information.");
114    }
115
116    /** Clean up resources since panel is being closed. */
117    @Override
118    public void removeNotify() {
119        super.removeNotify();
120        _player = null;
121        StateChangeMonitor.getInstance().removeStateChangeListener(WorkflowRun.WORKFLOWRUN_SELECTED, this);
122    }
123    
124    /** Set the parent frame. */
125    @Override
126    public void setParentFrame(TableauFrame parent) {
127        
128        super.setParentFrame(parent);
129        
130        // get the workflow run manager object.
131        WorkflowRunManagerManager wrmm = WorkflowRunManagerManager.getInstance();
132        // TODO getting the same workflow run manager regardless of parent frame.
133        // looks like there is a mapping from frame to wrm implying a single wrm
134        // per frame, but profiling module adds a second wrm to the frame.
135        _workflowRunManager = wrmm.getWRM(parent);
136        StateChangeMonitor.getInstance().addStateChangeListener(WorkflowRun.WORKFLOWRUN_SELECTED, this);
137    }
138
139    /** A factory to create the tab pane. */
140    public static class Factory extends TabPaneFactory {
141
142        public Factory(NamedObj container, String name)
143                throws IllegalActionException, NameDuplicationException {
144            super(container, name);
145        }
146
147        @Override
148        public TabPane createTabPane(TableauFrame parent) {
149            PreviousExecutionPanel pane = new PreviousExecutionPanel(getName());
150            return pane;
151        }
152    }
153    
154    /** Replay the last execution using the record player constructed
155     *  when the workflow run was selected in the workflow run manager.
156     */
157    @Override
158    protected void _replay() {
159        _executor.execute(new Runnable() {
160            @Override
161            public void run() {
162                try {
163                    _player.play(_execId);
164                } catch (Exception e) {
165                    MessageHandler.error("Error replaying execution.", e);
166                }
167            }
168        });
169    }
170    
171    /** The workflow run manager object. */
172    private WorkflowRunManager _workflowRunManager;
173    
174    private RecordPlayer _player;
175    
176    private Integer _execId;
177    
178    /** Single thread to replay previous workflows in. */
179    private ExecutorService _executor = Executors.newSingleThreadExecutor();
180}