View Javadoc

1   /*
2    * Copyright (c) 2005, The K-Wf Grid Consortium
3    * Fraunhofer Institute for Computer Architecture and Software Technology
4    * See http://www.kwfgrid.eu and http://www.first.fraunhofer.de for more details.
5    */
6   package net.kwfgrid.gwui;
7   
8   import net.kwfgrid.gworkflowdl.structure.Workflow;
9   
10  import org.glassbox.Theme;
11  import org.glassbox.SwingFactory;
12  import org.glassbox.SwingThread;
13  import org.glassbox.gui.*;
14  import org.glassbox.executor.Executor;
15  import org.glassbox.widgets.VisibleExecutor;
16  import org.glassbox.widgets.StatusBarExecutor;
17  
18  import javax.swing.*;
19  import java.awt.*;
20  import java.awt.event.ActionEvent;
21  
22  import org.apache.log4j.Logger;
23  
24  /***
25     Widget to start/stop/pause the Workflow.
26     This widget has the following properties which can be configured in the application's theme:
27     <ul>
28     <li>kwfgrid.WorkflowController.start.icon</li>
29     <li>kwfgrid.WorkflowController.stop.icon</li>
30     <li>kwfgrid.WorkflowController.pause.icon</li>
31     <li>kwfgrid.WorkflowController.task.background.color</li>
32     <li>kwfgrid.WorkflowController.task.text.color</li>
33     <li>kwfgrid.WorkflowController.task.insets</li>
34     <li>kwfgrid.WorkflowController.task.font</li>
35     <li>kwfgrid.Toolbar.button.background.color</li>
36     <li>kwfgrid.Toolbar.button.border.color</li>
37     <li>kwfgrid.Toolbar.button.insets</li>
38     <li>kwfgrid.Toolbar.background.color</li>
39     <li>kwfgrid.Toolbar.border.color</li>VisibleExecutor;
40     <li>kwfgrid.Toolbar.insets</li>
41     <li>kwfgrid.Toolbar.layout-gap.size</li>
42     </ul>
43   */
44  public class WorkflowController extends AbstractMember implements VisibleMember {
45      public static final String IDENTIFIER = "net.kwfgrid.gwui.WorkflowController";
46  
47      private class StartAction extends AbstractAction {
48  	public StartAction() {
49  	    super(null, START_ICON);
50  	}
51  
52  	public void actionPerformed(ActionEvent e) {
53  	    setPerformingAction(true);
54  	    _executor.execute(new StartTask(getWorkflowID()));
55  	}
56      }
57  
58      private class ResumeAction extends AbstractAction {
59  	public ResumeAction() {
60  	    super(null, START_ICON);
61  	}
62  
63  	public void actionPerformed(ActionEvent e) {
64  	    setPerformingAction(true);
65  	    _executor.execute(new ResumeTask(getWorkflowID()));	    
66  	}
67      }
68  
69      private class AbortAction extends AbstractAction {
70  	public AbortAction() {
71  	    super(null, ABORT_ICON);
72  	}
73  
74  	public void actionPerformed(ActionEvent e) {
75  	    setPerformingAction(true);
76  	    _executor.execute(new AbortTask(getWorkflowID()));
77  	}
78      }
79  
80      private class SuspendAction extends AbstractAction {
81  	public SuspendAction() {
82  	    super(null, SUSPEND_ICON);
83  	}
84  
85  	public void actionPerformed(ActionEvent e) {
86  	    setPerformingAction(true);
87  	    _executor.execute(new SuspendTask(getWorkflowID()));
88  	}
89      }
90  
91      private class StartTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task {
92  	private JComponent _view = SwingFactory.createLabel(getMessage(), TASK_THEME_PREFIX);
93  	private String _wfid;
94  
95  	public StartTask(String wfid) {
96  	    _wfid = wfid;
97  	}
98  
99  	public JComponent getView() {
100 	    return _view;
101 	}
102 
103 	public String getMessage() {
104 	    return "Starting workflow ...";
105 	}
106 
107 	public void run() {
108 	    try {
109 		_gwes.start(_wfid);
110 	    } catch (Exception x) {
111 		logger.warn("Could not start workflow.", x);
112 		JDialog e = SwingFactory2.createErrorDialog("Error", "Workflow could not be started.", x);
113 		e.show();
114 	    } 
115         setPerformingAction(false);
116 	}
117     }
118 
119     private class ResumeTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task {	
120 	private JComponent _view = SwingFactory.createLabel(getMessage(), TASK_THEME_PREFIX);
121 	private String _wfid;
122 
123 	public ResumeTask(String wfid) {
124 	    _wfid = wfid;
125 	}
126 
127 	public JComponent getView() {
128 	    return _view;
129 	}
130 
131 	public String getMessage() {
132 	    return "Resuming workflow ...";
133 	}
134 
135 	public void run() {
136 	    try {
137 		_gwes.resume(_wfid);
138 	    } catch (Exception x) {
139 		logger.warn("Could not start workflow.", x);
140 		JDialog e = SwingFactory2.createErrorDialog("Error", "Workflow could not be resumed.", x);
141 		e.show();
142 	    }
143 	    setPerformingAction(false);
144 	}
145     }
146 
147     private class AbortTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task {
148 	private JComponent _view = SwingFactory.createLabel(getMessage(), TASK_THEME_PREFIX);
149 	private String _wfid;
150 
151 	public AbortTask(String wfid) {
152 	    _wfid = wfid;
153 	}
154 
155 
156 	public JComponent getView() {
157 	    return _view;
158 	}
159 
160 	public String getMessage() {
161 	    return "Aborting workflow ...";
162 	}
163 
164 	public void run() {
165 	    try {
166 		_gwes.abort(_wfid);
167 	    } catch (Exception x) {
168 		logger.warn("Could not start workflow.", x);
169 		JDialog e = SwingFactory2.createErrorDialog("Error", "Workflow could not be aborted.", x);
170 		e.show();
171 	    }
172 	    setPerformingAction(false);
173 	}
174     }
175 
176     private class SuspendTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task {
177 	private JComponent _view = SwingFactory.createLabel(getMessage(), TASK_THEME_PREFIX);
178 	private String _wfid;
179 
180 	public SuspendTask(String wfid) {
181 	    _wfid = wfid;
182 	}
183 
184 
185 	public JComponent getView() {
186 	    return _view;
187 	}
188 
189 	public String getMessage() {
190 	    return "Suspending workflow ...";
191 	}
192 
193 	public void run() {
194 	    try {
195 		_gwes.suspend(_wfid);
196 	    } catch (Exception x) {
197 		logger.warn("Could not start workflow.", x);
198 		JDialog e = SwingFactory2.createErrorDialog("Error", "Workflow could not be suspended.", x);
199 		e.show();
200 	    }
201 	    setPerformingAction(false);
202 	}
203     }
204 
205     
206     private Runnable UPDATE_STATE = new Runnable() {
207 	    public void run() { updateState(); }
208 	};
209 
210     /*** The prefix of the theme configuration of the visible tasks. */
211     private static final String TASK_THEME_PREFIX = "kwfgrid.WorkflowController.task";
212 
213     private static final String BUTTON_THEME_PREFIX = "kwfgrid.Toolbar.button";
214     private static final String PANEL_THEME_PREFIX = "kwfgrid.Toolbar";
215     private static final String START_ICON_KEY = "kwfgrid.WorkflowController.start.icon";
216     private static final String ABORT_ICON_KEY = "kwfgrid.WorkflowController.stop.icon";
217     private static final String SUSPEND_ICON_KEY = "kwfgrid.WorkflowController.pause.icon";
218     private static final String LAYOUT_GAP_KEY = "kwfgrid.Toolbar.layout-gap.size";
219     private static final Icon START_ICON = Theme.getIcon(START_ICON_KEY);
220     private static final Icon ABORT_ICON = Theme.getIcon(ABORT_ICON_KEY);
221     private static final Icon SUSPEND_ICON = Theme.getIcon(SUSPEND_ICON_KEY);
222     private static final Dimension LAYOUT_GAP = Theme.getSize(LAYOUT_GAP_KEY);
223 
224     private static final Logger logger = Logger.getLogger(WorkflowController.class);
225 
226     private Executor _executor;
227     private net.kwfgrid.gwes.GWES _gwes;
228     private boolean _performingaction;
229 
230     private JPanel _view;
231     private JButton _bstart, _babort, _bsuspend;
232 
233     public WorkflowController(Executor executor) throws Exception {
234 	_executor = executor;
235 	_gwes = GWUI.getInstance().getGWES();
236 	_view = null;
237 	_performingaction = false;
238     }
239     
240     protected String getWorkflowID() {
241 	Workflow wf = (Workflow)getGroup().getProperty(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY);
242 	return wf!=null?wf.getID():null;
243     }
244 
245     private void setPerformingAction(boolean perf) {
246 	_performingaction = perf;
247 	SwingThread.invokeAndWaitSilently(UPDATE_STATE);
248     }
249 
250     private void updateState() {
251 	logger.debug("updateState()");
252 	
253 	if (getGroup()!=null && _view!=null) {
254 	    Object modalmember = getGroup().getProperty(VisibleGroup.MODAL_MEMBER_KEY);
255 	    Object status = getGroup().getProperty(WorkflowGroup.WORKFLOW_STATUS_KEY);
256 	    Object appstatus = getGroup().getProperty(Group.APPLICATION_STATUS_KEY);
257 	    String workflowid = getWorkflowID();
258 
259 	    if (status==null) status = WorkflowGroup.STATUS_UNDEFINED;
260 
261 	    if (status.equals(WorkflowGroup.STATUS_UNDEFINED) ||
262 		status.equals(WorkflowGroup.STATUS_TERMINATED) ||
263 		status.equals(WorkflowGroup.STATUS_COMPLETED) ||
264 		Group.EXITING.equals(appstatus) ||
265 		workflowid==null) {
266 		_view.setVisible(false);
267 	    } else {
268 		_view.setVisible(true);
269 		if (modalmember!=null ||
270 		    _gwes==null ||
271 		    _performingaction) {
272 		    _bstart.setEnabled(false);
273 		    _babort.setEnabled(false);
274 		    _bsuspend.setEnabled(false);
275 		} else if (status.equals(WorkflowGroup.STATUS_INITIATED)) {
276 		    _bstart.setEnabled(true);
277 		    _babort.setEnabled(true);
278 		    _bsuspend.setEnabled(false);
279 		    _bstart.setAction(new StartAction());
280 		} else if (status.equals(WorkflowGroup.STATUS_RUNNING) ||
281 			   status.equals(WorkflowGroup.STATUS_ACTIVE)) {
282 		    _bstart.setEnabled(false);
283 		    _babort.setEnabled(true);
284 		    _bsuspend.setEnabled(true);
285 		} else if (status.equals(WorkflowGroup.STATUS_SUSPENDED)) {
286 		    _bstart.setEnabled(true);
287 		    _babort.setEnabled(true);
288 		    _bsuspend.setEnabled(false);
289 		    _bstart.setAction(new ResumeAction());
290 		}
291 	    }
292 	}
293 
294 	logger.debug("updateState.exit");
295     }
296     
297     public JComponent getView() {
298 	if (_view==null) {
299 	    _bstart = SwingFactory.createButton(BUTTON_THEME_PREFIX, START_ICON);
300 	    _bstart.setAction(new StartAction());
301 	    _babort =  SwingFactory.createButton(BUTTON_THEME_PREFIX, ABORT_ICON);
302 	    _babort.setAction(new AbortAction());
303 	    _bsuspend =  SwingFactory.createButton(BUTTON_THEME_PREFIX, SUSPEND_ICON);
304 	    _bsuspend.setAction(new SuspendAction());
305 	    _view = SwingFactory.createPanel(PANEL_THEME_PREFIX);
306 	    _view.setLayout(new FlowLayout(FlowLayout.LEFT, LAYOUT_GAP.width, LAYOUT_GAP.height));
307 	    _view.add(_bstart);
308 	    _view.add(_bsuspend);
309 	    _view.add(_babort);
310 	    _view.setSize(_view.getLayout().preferredLayoutSize(_view));
311 	    _view.validate();
312 	    updateState();
313 	}
314 	return _view;
315     }
316 
317     public String getIdentifier() {
318 	return IDENTIFIER;
319     }
320 
321     public void setGroup(Group group) {
322 	super.setGroup(group);
323 	updateState();
324     }
325 
326     public void groupPropertyChanged(String name, Object oldvalue, Object newvalue) {
327 	logger.debug("groupPropertyChanged("+name+", "+oldvalue+", "+newvalue+")");
328 
329 	if (name.equals(Group.APPLICATION_STATUS_KEY)) {
330 	    if (Group.EXITING.equals(newvalue)) {
331 		if (_view!=null) _view.setVisible(false);
332 	    } 
333 	} else if (name.equals(VisibleGroup.MODAL_MEMBER_KEY)) {
334 	    updateState();
335 	} else if (name.equals(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY)) {
336 	    updateState();
337 	} else if (name.equals(WorkflowGroup.WORKFLOW_STATUS_KEY)) {
338 	    updateState();
339 	}
340 
341 	logger.debug("groupPropertyChanged.exit");
342     }
343 }