1
2
3
4
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 }