1 package org
.argeo
.slc
.client
.ui
.editors
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Iterator
;
9 import javax
.jcr
.NodeIterator
;
10 import javax
.jcr
.Property
;
11 import javax
.jcr
.RepositoryException
;
12 import javax
.jcr
.Session
;
13 import javax
.jcr
.nodetype
.NodeType
;
14 import javax
.jcr
.observation
.Event
;
15 import javax
.jcr
.observation
.EventIterator
;
16 import javax
.jcr
.observation
.EventListener
;
17 import javax
.jcr
.observation
.ObservationManager
;
19 import org
.argeo
.ArgeoException
;
20 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
21 import org
.argeo
.jcr
.JcrUtils
;
22 import org
.argeo
.slc
.SlcException
;
23 import org
.argeo
.slc
.client
.ui
.SlcImages
;
24 import org
.argeo
.slc
.execution
.ExecutionProcess
;
25 import org
.argeo
.slc
.jcr
.SlcJcrUtils
;
26 import org
.argeo
.slc
.jcr
.SlcNames
;
27 import org
.argeo
.slc
.jcr
.SlcTypes
;
28 import org
.argeo
.slc
.process
.RealizedFlow
;
29 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
30 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
31 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
32 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
33 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
34 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
35 import org
.eclipse
.jface
.viewers
.TreeViewer
;
36 import org
.eclipse
.jface
.viewers
.Viewer
;
37 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
38 import org
.eclipse
.swt
.SWT
;
39 import org
.eclipse
.swt
.custom
.SashForm
;
40 import org
.eclipse
.swt
.dnd
.DND
;
41 import org
.eclipse
.swt
.dnd
.TextTransfer
;
42 import org
.eclipse
.swt
.dnd
.Transfer
;
43 import org
.eclipse
.swt
.dnd
.TransferData
;
44 import org
.eclipse
.swt
.events
.SelectionEvent
;
45 import org
.eclipse
.swt
.events
.SelectionListener
;
46 import org
.eclipse
.swt
.graphics
.Image
;
47 import org
.eclipse
.swt
.layout
.FillLayout
;
48 import org
.eclipse
.swt
.layout
.GridData
;
49 import org
.eclipse
.swt
.layout
.GridLayout
;
50 import org
.eclipse
.swt
.layout
.RowData
;
51 import org
.eclipse
.swt
.layout
.RowLayout
;
52 import org
.eclipse
.swt
.widgets
.Button
;
53 import org
.eclipse
.swt
.widgets
.Composite
;
54 import org
.eclipse
.swt
.widgets
.Label
;
55 import org
.eclipse
.ui
.PlatformUI
;
56 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
57 import org
.eclipse
.ui
.forms
.IManagedForm
;
58 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
59 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
60 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
62 public class ProcessBuilderPage
extends FormPage
implements SlcNames
, SlcTypes
{
63 public final static String ID
= "processBuilderPage";
64 // private final static Log log =
65 // LogFactory.getLog(ProcessBuilderPage.class);
67 private Node processNode
;
69 private TreeViewer flowsViewer
;
70 private Label statusLabel
;
72 private Button remove
;
75 private AbstractFormPart formPart
;
76 private EventListener statusObserver
;
78 public ProcessBuilderPage(ProcessEditor editor
, Node processNode
) {
79 super(editor
, ID
, "Definition");
80 this.processNode
= processNode
;
84 protected void createFormContent(IManagedForm mf
) {
86 ScrolledForm form
= mf
.getForm();
87 form
.setText("Process " + processNode
.getName());
88 GridLayout mainLayout
= new GridLayout(1, true);
89 form
.getBody().setLayout(mainLayout
);
91 createControls(form
.getBody());
92 createBuilder(form
.getBody());
95 formPart
= new AbstractFormPart() {
98 getManagedForm().addPart(formPart
);
101 statusObserver
= new AsyncUiEventListener() {
102 protected void onEventInUiThread(EventIterator events
) {
106 ObservationManager observationManager
= processNode
.getSession()
107 .getWorkspace().getObservationManager();
108 observationManager
.addEventListener(statusObserver
,
109 Event
.PROPERTY_CHANGED
, processNode
.getPath(), true, null,
112 } catch (RepositoryException e
) {
113 throw new ArgeoException("Cannot create form content", e
);
117 protected void createControls(Composite parent
) {
118 FormToolkit tk
= getManagedForm().getToolkit();
120 Composite controls
= tk
.createComposite(parent
);
121 controls
.setLayout(new RowLayout());
122 controls
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
124 run
= tk
.createButton(controls
, null, SWT
.PUSH
);
125 run
.setToolTipText("Run");
126 run
.setImage(SlcImages
.LAUNCH
);
127 run
.addSelectionListener(new SelectionListener() {
128 public void widgetSelected(SelectionEvent e
) {
129 if (isFinished(getProcessStatus())) {
132 ((ProcessEditor
) getEditor()).process();
136 public void widgetDefaultSelected(SelectionEvent e
) {
141 remove
= tk
.createButton(controls
, null, SWT
.PUSH
);
142 remove
.setImage(SlcImages
.REMOVE_ONE
);
143 remove
.setToolTipText("Remove selected flows");
144 remove
.addSelectionListener(new SelectionListener() {
145 public void widgetSelected(SelectionEvent e
) {
146 removeSelectedFlows();
149 public void widgetDefaultSelected(SelectionEvent e
) {
154 clear
= tk
.createButton(controls
, null, SWT
.PUSH
);
155 clear
.setImage(SlcImages
.REMOVE_ALL
);
156 clear
.setToolTipText("Clear all flows");
157 clear
.addSelectionListener(new SelectionListener() {
158 public void widgetSelected(SelectionEvent e
) {
162 public void widgetDefaultSelected(SelectionEvent e
) {
167 Composite statusComposite
= tk
.createComposite(controls
);
168 RowData rowData
= new RowData();
171 statusComposite
.setLayoutData(rowData
);
172 statusComposite
.setLayout(new FillLayout());
173 statusLabel
= tk
.createLabel(statusComposite
, getProcessStatus());
175 // make sure all controls are in line with status
179 protected void relaunch() {
181 Node duplicatedNode
= duplicateProcess();
184 .getActiveWorkbenchWindow()
187 new ProcessEditorInput(duplicatedNode
.getPath()),
189 getEditor().close(false);
190 } catch (Exception e1
) {
191 throw new SlcException("Cannot relaunch " + processNode
, e1
);
195 protected Node
duplicateProcess() {
197 Session session
= processNode
.getSession();
198 String uuid
= UUID
.randomUUID().toString();
199 String destPath
= SlcJcrUtils
.createExecutionProcessPath(uuid
);
200 Node newNode
= JcrUtils
.mkdirs(session
, destPath
, SLC_PROCESS
);
201 JcrUtils
.copy(processNode
, newNode
);
202 // session.getWorkspace().copy(processNode.getPath(), destPath);
203 // Node newNode = session.getNode(destPath);
204 // make sure that we kept the mixins
205 // newNode.addMixin(NodeType.MIX_CREATED);
206 // newNode.addMixin(NodeType.MIX_LAST_MODIFIED);
207 newNode
.setProperty(SLC_UUID
, uuid
);
208 newNode
.setProperty(SLC_STATUS
, ExecutionProcess
.INITIALIZED
);
211 } catch (RepositoryException e
) {
212 throw new SlcException("Cannot duplicate process", e
);
216 protected String
getProcessStatus() {
218 return processNode
.getProperty(SLC_STATUS
).getString();
219 } catch (RepositoryException e
) {
220 throw new SlcException("Cannot retrieve status for " + processNode
,
225 protected void statusChanged() {
226 String status
= getProcessStatus();
227 statusLabel
.setText(status
);
228 Boolean isEditable
= isEditable(status
);
229 run
.setEnabled(isEditable
);
230 remove
.setEnabled(isEditable
);
231 clear
.setEnabled(isEditable
);
232 // flowsViewer.getTree().setEnabled(isEditable);
233 if (status
.equals(ExecutionProcess
.COMPLETED
)
234 || status
.equals(ExecutionProcess
.ERROR
)) {
235 run
.setEnabled(true);
236 run
.setImage(SlcImages
.RELAUNCH
);
237 run
.setToolTipText("Relaunch");
241 /** Optimization so that we don't call the node each time */
242 protected Boolean
isEditable(String status
) {
243 return status
.equals(ExecutionProcess
.NEW
)
244 || status
.equals(ExecutionProcess
.INITIALIZED
);
247 protected Boolean
isFinished(String status
) {
248 return status
.equals(ExecutionProcess
.COMPLETED
)
249 || status
.equals(ExecutionProcess
.ERROR
);
252 protected void createBuilder(Composite parent
) {
253 FormToolkit tk
= getManagedForm().getToolkit();
254 SashForm sashForm
= new SashForm(parent
, SWT
.HORIZONTAL
);
255 sashForm
.setSashWidth(4);
256 sashForm
.setLayout(new FillLayout());
257 sashForm
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
259 Composite top
= tk
.createComposite(sashForm
);
260 GridLayout gl
= new GridLayout(1, false);
263 flowsViewer
= new TreeViewer(top
);
264 flowsViewer
.getTree().setLayoutData(
265 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
266 flowsViewer
.setLabelProvider(new ViewLabelProvider());
267 flowsViewer
.setContentProvider(new ViewContentProvider());
268 flowsViewer
.addSelectionChangedListener(new SelectionChangedListener());
270 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
271 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
272 flowsViewer
.addDropSupport(operations
, tt
, new ViewDropListener(
275 flowsViewer
.setInput(getEditorSite());
276 flowsViewer
.setInput(processNode
);
278 Composite bottom
= tk
.createComposite(sashForm
);
279 bottom
.setLayout(new GridLayout(1, false));
280 sashForm
.setWeights(getWeights());
283 protected int[] getWeights() {
284 return new int[] { 70, 30 };
290 protected void addFlow(String path
) {
292 Node flowNode
= processNode
.getNode(SLC_FLOW
).addNode(SLC_FLOW
);
293 flowNode
.addMixin(SLC_REALIZED_FLOW
);
294 Node address
= flowNode
.addNode(SLC_ADDRESS
, NodeType
.NT_ADDRESS
);
295 address
.setProperty(Property
.JCR_PATH
, path
);
296 flowsViewer
.refresh();
297 formPart
.markDirty();
298 } catch (RepositoryException e
) {
299 throw new SlcException("Cannot drop " + path
, e
);
303 @SuppressWarnings("unchecked")
304 protected void removeSelectedFlows() {
305 if (!flowsViewer
.getSelection().isEmpty()) {
306 Iterator
<Object
> it
= ((StructuredSelection
) flowsViewer
307 .getSelection()).iterator();
308 while (it
.hasNext()) {
309 Node node
= (Node
) it
.next();
312 } catch (RepositoryException e
) {
313 throw new ArgeoException("Cannot remove " + node
, e
);
316 flowsViewer
.refresh();
317 formPart
.markDirty();
321 protected void removeAllFlows() {
323 for (NodeIterator nit
= processNode
.getNode(SLC_FLOW
).getNodes(); nit
325 nit
.nextNode().remove();
327 flowsViewer
.refresh();
328 formPart
.markDirty();
329 } catch (RepositoryException e
) {
330 throw new ArgeoException("Cannot remove flows from " + processNode
,
335 public void commit(Boolean onSave
) {
337 statusLabel
.setText(getProcessStatus());
338 formPart
.commit(onSave
);
342 public void dispose() {
343 JcrUtils
.unregisterQuietly(processNode
, statusObserver
);
347 // Specific Providers for the current view.
348 protected class ViewContentProvider
implements ITreeContentProvider
{
349 public void inputChanged(Viewer arg0
, Object arg1
, Object arg2
) {
352 public void dispose() {
355 public Object
[] getElements(Object obj
) {
356 if (!(obj
instanceof Node
))
357 return new Object
[0];
360 Node node
= (Node
) obj
;
361 List
<Node
> children
= new ArrayList
<Node
>();
362 for (NodeIterator nit
= node
.getNode(SLC_FLOW
).getNodes(); nit
364 children
.add(nit
.nextNode());
365 return children
.toArray();
366 } catch (RepositoryException e
) {
367 throw new SlcException("Cannot list children of " + obj
, e
);
371 public Object
[] getChildren(Object parentElement
) {
375 public Object
getParent(Object element
) {
379 public boolean hasChildren(Object element
) {
385 protected class ViewLabelProvider
extends ColumnLabelProvider
{
388 public String
getText(Object element
) {
389 Node node
= (Node
) element
;
391 if (node
.isNodeType(SLC_REALIZED_FLOW
)) {
392 if (node
.hasNode(SLC_ADDRESS
)) {
393 String path
= node
.getNode(SLC_ADDRESS
)
394 .getProperty(Property
.JCR_PATH
).getString();
395 return SlcJcrUtils
.flowExecutionModuleName(path
) + ":"
396 + SlcJcrUtils
.flowRelativePath(path
);
399 } catch (RepositoryException e
) {
400 throw new SlcException("Cannot display " + element
, e
);
402 return super.getText(element
);
406 public Image
getImage(Object element
) {
407 Node node
= (Node
) element
;
409 if (node
.isNodeType(SLC_REALIZED_FLOW
)) {
410 return SlcImages
.FLOW
;
412 } catch (RepositoryException e
) {
413 throw new SlcException("Cannot display " + element
, e
);
415 return super.getImage(element
);
420 // Parameter view is updated each time a new line is selected
421 class SelectionChangedListener
implements ISelectionChangedListener
{
422 public void selectionChanged(SelectionChangedEvent evt
) {
424 IStructuredSelection curSelection
= (IStructuredSelection
) evt
426 Object obj
= curSelection
.getFirstElement();
428 if (obj
instanceof RealizedFlow
) {
429 // RealizedFlow rf = (RealizedFlow) obj;
430 // curSelectedRow = realizedFlows.indexOf(rf);
431 // refreshParameterview();
437 protected class ViewDropListener
extends ViewerDropAdapter
{
439 public ViewDropListener(Viewer viewer
) {
444 public boolean performDrop(Object data
) {
445 String path
= data
.toString();
451 public boolean validateDrop(Object target
, int operation
,
452 TransferData transferType
) {
453 return isEditable(getProcessStatus());