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   import net.kwfgrid.gworkflowdl.structure.JdomString;
10  
11  import org.glassbox.gui.*;
12  import org.glassbox.executor.Executor;
13  import org.glassbox.widgets.VisibleExecutor;
14  import org.glassbox.widgets.StatusBarExecutor;
15  import org.glassbox.Theme;
16  import org.glassbox.SwingFactory;
17  import org.glassbox.SwingThread;
18  
19  import javax.swing.*;
20  import java.awt.event.ActionEvent;
21  import java.awt.event.ActionListener;
22  import java.awt.Dimension;
23  import java.awt.FlowLayout;
24  import java.io.*;
25  
26  import org.apache.log4j.Logger;
27  
28  /***
29     A widget to load a new workflow from a local file.
30     This widget has the following properties which can be configured in the application's theme:<br>
31     <ul>
32     <li>kwfgrid.WorkflowLoader.button.icon</li>
33     <li>kwfgrid.WorkflowLoader.button-save.icon</li>
34     <li>kwfgrid.WorkflowLoader.idfield.size</li>
35     <li>kwfgrid.WorkflowLoader.task.background.color</li>
36     <li>kwfgrid.WorkflowLoader.task.text.color</li>
37     <li>kwfgrid.WorkflowLoader.task.insets</li>
38     <li>kwfgrid.WorkflowLoader.task.font</li>
39     <li>kwfgrid.Toolbar.background.color</li>
40     <li>kwfgrid.Toolbar.border.color</li>
41     <li>kwfgrid.Toolbar.insets</li>
42     <li>kwfgrid.Toolbar.layout-gap.size</li>
43     <li>kwfgrid.Toolbar.button.background.color</li>
44     <li>kwfgrid.Toolbar.button.border.color</li>
45     <li>kwfgrid.Toolbar.button.insets</li>
46     </ul>
47   */
48  public class WorkflowLoader extends AbstractMember implements VisibleMember {
49      public static final String IDENTIFIER = "net.kwfgrid.gwui.WorkflowLoader";
50      
51      private class LoadAction extends AbstractAction {
52  	public LoadAction(Icon icon) {
53  	    super(null, icon);
54  	}
55  
56  	public void actionPerformed(ActionEvent e) {
57  	    setPerformingAction(true);
58  	    getGroup().setProperty(VisibleGroup.MODAL_MEMBER_KEY, WorkflowLoader.this);
59  	    int ret = _chooser.showOpenDialog(null);
60  	    getGroup().setProperty(VisibleGroup.MODAL_MEMBER_KEY, null);
61  	    if( ret == JFileChooser.APPROVE_OPTION ) {
62  		File file   = _chooser.getSelectedFile();
63  		getGroup().setProperty(WorkflowGroup.WORKFLOW_STATUS_KEY, WorkflowGroup.STATUS_UNDEFINED);
64  		logger.debug("Executing InitiateTask for "+file);
65  		_executor.execute(new InitiateTask(file));
66  		logger.debug("InitiateTask submitted to executor.");
67  	    } else {
68  		setPerformingAction(false);
69  	    }
70  	}
71      }
72  
73      private class SaveAction extends AbstractAction {
74  	public SaveAction(Icon icon) {
75  	    super(null, icon);
76  	}
77  
78  	public void actionPerformed(ActionEvent e) {
79  	    setPerformingAction(true);
80  	    getGroup().setProperty(VisibleGroup.MODAL_MEMBER_KEY, WorkflowLoader.this);
81  	    int ret = _chooser.showSaveDialog(null);
82  	    getGroup().setProperty(VisibleGroup.MODAL_MEMBER_KEY, null);
83  	    try {
84  		if( ret == JFileChooser.APPROVE_OPTION ) {
85  		    File file   = _chooser.getSelectedFile();
86  		    String gworkflowdl = getWorkflowDescription();
87  		    _executor.execute(new SaveTask(file, gworkflowdl));
88  		} else {
89  		    setPerformingAction(false);
90  		}
91  	    } catch (IOException x) {
92  		logger.error("Could not save workflow description.", x);
93  		JDialog ee = SwingFactory2.createErrorDialog("Error", "Could not save workflow description.", x);
94  		ee.show();
95  	    }
96  	}
97      }
98  
99      private class InitiateTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task {
100 	private JComponent _view; 
101 	private File _file;
102 	private String _message;
103 
104 	public InitiateTask(File file) {
105 	    _file = file;
106 	    _message = "Initiating new workflow from file "+file.getAbsolutePath()+" ...";
107 	    _view = null;
108 	}
109 
110 	public JComponent getView() {
111 	    if (_view == null) {
112 		_view = SwingFactory.createLabel(_message, TASK_THEME_PREFIX);
113 	    }
114 	    return _view;
115 	}
116 
117 	public String getMessage() {
118 	    return _message;
119 	}
120 
121 	public void run() {
122 	    try {
123 		logger.debug("Reading workflow description ...");
124 
125 		String gworkflowdl = GWUI.readFile(_file.toString());
126 
127 		logger.debug("Calling GWES.initiate ...");
128 
129 		String workflowid = _gwes.initiate(gworkflowdl, _userid);
130 
131 		logger.debug("Got workflow ID "+workflowid);
132 
133 		_group.setWorkflowID(workflowid);
134 	    } catch (Exception x) {
135 		logger.warn("Could not initiate workflow.", x);
136 		JDialog e = SwingFactory2.createErrorDialog("Error", "Workflow could not be initiated.", x);
137 		e.show();
138 	    }
139 	    setPerformingAction(false);
140 	}
141     }
142 
143     private class SaveTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task { 
144 	private JComponent _view; 
145 	private String _gworkflowdl;
146 	private File _file;
147 	private String _message;
148 
149 	public SaveTask(File file, String gworkflowdl) {
150 	    _gworkflowdl = gworkflowdl;
151 	    _file = file;
152 	    _message = "Saving workflow to "+file.getAbsolutePath()+" ...";
153 	    _view = null;
154 	}
155 
156 	public JComponent getView() {
157 	    if (_view == null) {
158 		_view = SwingFactory.createLabel(_message, TASK_THEME_PREFIX);
159 	    }
160 	    return _view;
161 	}
162 
163 	public String getMessage() {
164 	    return _message;
165 	}
166 
167 	public void run() {
168 	    try {
169 		logger.debug("Writing workflow to "+_file.getAbsolutePath());
170 		
171 		GWUI.writeFile(_file, _gworkflowdl);
172 	    } catch (Exception x) {
173 		logger.warn("Could not save workflow.", x);
174 		JDialog e = SwingFactory2.createErrorDialog("Error", "Could not save workflow description.", x);
175 		e.show();
176 	    }
177 	    setPerformingAction(false);
178 	}
179     }
180 
181     private class OpenWorkflowTask implements VisibleExecutor.VisibleTask, StatusBarExecutor.Task {
182 	private JComponent _view;
183 	private String _message;
184 	private String _workflowid;
185 	
186 	public OpenWorkflowTask(String workflowid) {
187 	    _workflowid = workflowid;
188 	    _message = "Opening workflow ...";
189 	    _view = null;
190 	}
191 
192 	public String getMessage() {
193 	    return _message;
194 	}
195 
196 	public JComponent getView() {
197 	    if (_view == null) {
198 		_view = SwingFactory.createLabel(_message, TASK_THEME_PREFIX);
199 	    }
200 	    return _view;
201 	}
202 
203 	public void run() {
204 	    try {
205 		logger.debug("Opening workflow ...");		
206 		_group.setWorkflowID(_workflowid);
207 	    } catch (Exception x) {
208 		logger.warn("Could not open workflow.", x);
209 		JDialog e = SwingFactory2.createErrorDialog("Error", "Could not open workflow.", x);
210 		e.show();
211 	    }		
212 	    setPerformingAction(false);
213 	    getGroup().setProperty(VisibleGroup.MODAL_MEMBER_KEY, null);
214 	}
215     }
216 
217     private ActionListener IDFIELD_LISTENER = new ActionListener() {
218 	    public void actionPerformed(ActionEvent e) {
219 		setPerformingAction(true);
220 		getGroup().setProperty(VisibleGroup.MODAL_MEMBER_KEY, WorkflowLoader.this);
221 		_executor.execute(new OpenWorkflowTask(e.getActionCommand())); 
222 	    }
223 	};
224 
225     private Runnable UPDATE_STATE = new Runnable() {
226 	    public void run() { updateState(); }
227 	};
228 
229     private static final Logger logger = Logger.getLogger(WorkflowLoader.class);
230 
231     private static final String BUTTON_THEME_PREFIX = "kwfgrid.Toolbar.button";
232     private static final String TASK_THEME_PREFIX = "kwfgrid.WorkflowLoader.task";
233     private static final String PANEL_THEME_PREFIX = "kwfgrid.Toolbar";
234     private static final String ICON_KEY = "kwfgrid.WorkflowLoader.button.icon";
235     private static final String ICON_SAVE_KEY = "kwfgrid.WorkflowLoader.button-save.icon";    
236     private static final String IDFIELD_THEME_PREFIX = "kwfgrid.WorkflowLoader.idfield";
237     private static final String IDFIELD_SIZE_KEY = "kwfgrid.WorkflowLoader.idfield.size";    
238     private static final Icon ICON = Theme.getIcon(ICON_KEY);
239     private static final Icon ICON_SAVE = Theme.getIcon(ICON_SAVE_KEY);
240     private static final String LAYOUT_GAP_KEY = "kwfgrid.Toolbar.layout-gap.size";
241     private static final Dimension LAYOUT_GAP = Theme.getSize(LAYOUT_GAP_KEY);
242     private static final Dimension IDFIELD_SIZE = Theme.getSize(IDFIELD_SIZE_KEY);
243 
244     private JFileChooser _chooser;
245     private Executor _executor;
246     private JPanel _view;
247     private JButton _button;
248     private JButton _buttonsave;
249     private JTextField _idfield;
250     private net.kwfgrid.gwes.GWES _gwes;
251     private boolean _performingaction;
252     private String _userid;
253     private WorkflowGroup _group;
254     
255     public WorkflowLoader(Executor executor, WorkflowGroup group) throws Exception {
256 	_group = group;
257 	_executor = executor;
258 	_view = null;
259 	_button = null;
260 	_buttonsave = null;
261 	_idfield = null;
262 	_chooser = null;
263 	_gwes = GWUI.getInstance().getGWES();
264 	_performingaction = false;
265 	_userid = (String)GWUI.getInstance().getProperty(GWUI.USER_ID_KEY);
266     }
267     
268     protected String getWorkflowDescription() throws IOException {
269 	if (getGroup() == null) return null;
270 	Workflow wf = (Workflow)getGroup().getProperty(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY);
271 	if (wf == null) return null;
272 	return JdomString.workflow2string(wf);
273     }
274 
275     private String getWorkflowID() {
276 	if (getGroup() == null) return null;
277 	Workflow wf = (Workflow)getGroup().getProperty(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY);
278 	if (wf == null) return null;
279 	return wf.getID();
280     }
281 
282     private String getIDFieldText() {
283 	String text = getWorkflowID();
284 	if (text == null) return "Enter Workflow ID";
285 	else return text;
286     }
287 
288     private void setPerformingAction(boolean p) {
289 	_performingaction = p;
290 
291 	SwingThread.invokeAndWaitSilently(UPDATE_STATE);
292     }
293 
294     private void updateState() {
295 	logger.debug("updateState()");
296 	
297 	if (getGroup()!=null && _view!=null) {
298 	    Object modalmember = getGroup().getProperty(VisibleGroup.MODAL_MEMBER_KEY);
299 	    Object status = getGroup().getProperty(WorkflowGroup.WORKFLOW_STATUS_KEY);
300 	    Object appstatus = getGroup().getProperty(Group.APPLICATION_STATUS_KEY);
301 	    
302 	    logger.debug("Modalmember: "+modalmember);
303 	    logger.debug("status: "+status);
304 	    logger.debug("appstatus: "+appstatus);
305 	    logger.debug("performingaction: "+_performingaction);
306 
307 	    if (status==null) status = WorkflowGroup.STATUS_UNDEFINED;
308 	    
309 	    if (Group.EXITING.equals(appstatus)) {
310 		_view.setVisible(false);
311 	    } else {
312 		_view.setVisible(true);
313 		if (modalmember!=null || _performingaction) {
314 		    _button.setEnabled(false);
315 		    _button.setToolTipText(null);
316 		    _buttonsave.setEnabled(false);
317 		    _buttonsave.setToolTipText(null);
318 		    _idfield.setEnabled(false);
319 		    _idfield.setToolTipText(null);
320 		} else {
321 		    _button.setEnabled(true);
322 		    _button.setToolTipText("Initiate new Workflow from local File");
323 		    boolean cansave = !status.equals(WorkflowGroup.STATUS_UNDEFINED);
324 		    _buttonsave.setEnabled(cansave);
325 		    _buttonsave.setToolTipText(cansave?
326 					       "Save workflow description to local disc.":
327 					       null);
328 		    _idfield.setEnabled(true);
329 		    _idfield.setToolTipText(getWorkflowID()==null?
330 					    "Enter workflow ID to show according workflow.":
331 					    "Workflow ID. Enter different ID to show according workflow.");
332 		}
333 	    }
334 	}
335 
336 	logger.debug("updateState.exit");
337     }
338 
339     private void updateView() {
340 	updateState();
341 	_idfield.setText(getIDFieldText());	
342     }
343     
344     public JComponent getView() {
345 	if (_view==null) {
346 	    _chooser = SwingFactory2.getFileChooser(GWUI.WORKFLOW_FILE_CHOOSER);
347 	    _button = SwingFactory.createButton(BUTTON_THEME_PREFIX);
348 	    _button.setAction(new LoadAction(ICON));
349 	    _buttonsave = SwingFactory.createButton(BUTTON_THEME_PREFIX);
350 	    _buttonsave.setAction(new SaveAction(ICON_SAVE));
351 	    _idfield = SwingFactory.createTextField(IDFIELD_THEME_PREFIX);
352 	    _idfield.setColumns(IDFIELD_SIZE.width);
353 	    _idfield.setText(getIDFieldText());
354 	    _idfield.addActionListener(IDFIELD_LISTENER);
355 	    _view = SwingFactory.createPanel(PANEL_THEME_PREFIX);
356 	    _view.setLayout(new FlowLayout(FlowLayout.LEFT, LAYOUT_GAP.width, LAYOUT_GAP.height));
357 	    _view.add(_button);
358 	    _view.add(_buttonsave);
359 	    _view.add(_idfield);
360 	    _view.setSize(_view.getLayout().preferredLayoutSize(_view));
361 	    _view.validate();
362 	    updateState();
363 	}
364 	return _view;
365     }
366 
367     public String getIdentifier() {
368 	return IDENTIFIER;
369     }
370 
371     public void groupPropertyChanged(String name, Object oldvalue, Object newvalue) {
372 	logger.debug("groupPropertyChanged("+name+", "+oldvalue+", "+newvalue+")");
373 
374 	if (name.equals(Group.APPLICATION_STATUS_KEY)) {
375 	    if (Group.EXITING.equals(newvalue)) {
376 		if (_view!=null) _view.setVisible(false);
377 	    } 
378 	} else if (name.equals(VisibleGroup.MODAL_MEMBER_KEY)) {
379 	    updateState();
380 	} else if (name.equals(WorkflowGroup.WORKFLOW_STATUS_KEY)) {
381 	    updateState();
382 	} else if (name.equals(WorkflowGroup.ACTIVE_WORKFLOW_DOCUMENT_KEY)) {
383 	    updateView();
384 	}
385 
386 	logger.debug("groupPropertyChanged.exit");
387     }
388 }