2 * Copyright (C) 2007-2012 Argeo GmbH
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org
.argeo
.slc
.client
.ui
.editors
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Iterator
;
20 import java
.util
.List
;
21 import java
.util
.SortedSet
;
22 import java
.util
.TreeSet
;
24 import javax
.jcr
.LoginException
;
25 import javax
.jcr
.Node
;
26 import javax
.jcr
.NodeIterator
;
27 import javax
.jcr
.Property
;
28 import javax
.jcr
.RepositoryException
;
29 import javax
.jcr
.Session
;
30 import javax
.jcr
.nodetype
.NodeType
;
31 import javax
.jcr
.observation
.Event
;
32 import javax
.jcr
.observation
.EventListener
;
33 import javax
.jcr
.observation
.ObservationManager
;
34 import javax
.jcr
.query
.Query
;
35 import javax
.jcr
.query
.QueryManager
;
37 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
38 import org
.argeo
.jcr
.JcrUtils
;
39 import org
.argeo
.slc
.SlcException
;
40 import org
.argeo
.slc
.SlcNames
;
41 import org
.argeo
.slc
.SlcTypes
;
42 import org
.argeo
.slc
.client
.ui
.SlcImages
;
43 import org
.argeo
.slc
.execution
.ExecutionProcess
;
44 import org
.argeo
.slc
.jcr
.SlcJcrUtils
;
45 import org
.argeo
.slc
.primitive
.PrimitiveAccessor
;
46 import org
.argeo
.slc
.primitive
.PrimitiveUtils
;
47 import org
.eclipse
.jface
.viewers
.CellEditor
;
48 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
49 import org
.eclipse
.jface
.viewers
.ColumnViewer
;
50 import org
.eclipse
.jface
.viewers
.ComboBoxCellEditor
;
51 import org
.eclipse
.jface
.viewers
.EditingSupport
;
52 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
53 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
54 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
55 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
56 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
57 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
58 import org
.eclipse
.jface
.viewers
.TableViewer
;
59 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
60 import org
.eclipse
.jface
.viewers
.TextCellEditor
;
61 import org
.eclipse
.jface
.viewers
.TreeViewer
;
62 import org
.eclipse
.jface
.viewers
.Viewer
;
63 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
64 import org
.eclipse
.swt
.SWT
;
65 import org
.eclipse
.swt
.custom
.SashForm
;
66 import org
.eclipse
.swt
.dnd
.DND
;
67 import org
.eclipse
.swt
.dnd
.TextTransfer
;
68 import org
.eclipse
.swt
.dnd
.Transfer
;
69 import org
.eclipse
.swt
.dnd
.TransferData
;
70 import org
.eclipse
.swt
.events
.SelectionEvent
;
71 import org
.eclipse
.swt
.events
.SelectionListener
;
72 import org
.eclipse
.swt
.graphics
.Image
;
73 import org
.eclipse
.swt
.layout
.FillLayout
;
74 import org
.eclipse
.swt
.layout
.GridData
;
75 import org
.eclipse
.swt
.layout
.GridLayout
;
76 import org
.eclipse
.swt
.layout
.RowData
;
77 import org
.eclipse
.swt
.layout
.RowLayout
;
78 import org
.eclipse
.swt
.widgets
.Button
;
79 import org
.eclipse
.swt
.widgets
.Composite
;
80 import org
.eclipse
.swt
.widgets
.Label
;
81 import org
.eclipse
.swt
.widgets
.Menu
;
82 import org
.eclipse
.swt
.widgets
.MenuItem
;
83 import org
.eclipse
.swt
.widgets
.Table
;
84 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
85 import org
.eclipse
.ui
.forms
.IManagedForm
;
86 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
87 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
88 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
90 /** Definition of the process. */
91 public class ProcessBuilderPage
extends FormPage
implements SlcNames
{
92 // private final static Log log =
93 // LogFactory.getLog(ProcessBuilderPage.class);
95 public final static String ID
= "processBuilderPage";
97 /** To be displayed in empty lists */
98 final static String NONE
= "<none>";
100 private Node processNode
;
101 private Session agentSession
;
103 private TreeViewer flowsViewer
;
104 private TableViewer valuesViewer
;
105 private Label statusLabel
;
107 private Button remove
;
108 private Button clear
;
110 private AbstractFormPart formPart
;
111 private EventListener statusObserver
;
113 public ProcessBuilderPage(ProcessEditor editor
, Node processNode
) {
114 super(editor
, ID
, "Definition");
115 this.processNode
= processNode
;
117 this.agentSession
= processNode
.getSession().getRepository().login();
118 } catch (RepositoryException e
) {
119 throw new SlcException("Cannot open agent session", e
);
124 protected void createFormContent(IManagedForm mf
) {
126 ScrolledForm form
= mf
.getForm();
127 form
.setExpandHorizontal(true);
128 form
.setExpandVertical(true);
129 form
.setText("Process " + processNode
.getName());
130 GridLayout mainLayout
= new GridLayout(1, true);
131 form
.getBody().setLayout(mainLayout
);
133 createControls(form
.getBody());
134 createBuilder(form
.getBody());
137 formPart
= new AbstractFormPart() {
140 getManagedForm().addPart(formPart
);
143 statusObserver
= new AsyncUiEventListener(form
.getDisplay()) {
144 protected void onEventInUiThread(List
<Event
> events
) {
148 ObservationManager observationManager
= processNode
.getSession().getWorkspace().getObservationManager();
149 observationManager
.addEventListener(statusObserver
, Event
.PROPERTY_CHANGED
, processNode
.getPath(), true,
152 // make sure all controls are in line with status
158 } catch (RepositoryException e
) {
159 throw new SlcException("Cannot create form content", e
);
163 protected void createControls(Composite parent
) {
164 FormToolkit tk
= getManagedForm().getToolkit();
166 Composite controls
= tk
.createComposite(parent
);
167 controls
.setLayout(new RowLayout());
168 controls
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
170 run
= tk
.createButton(controls
, null, SWT
.PUSH
);
171 run
.setToolTipText("Run");
172 run
.setImage(SlcImages
.LAUNCH
);
173 run
.addSelectionListener(new SelectionListener() {
174 public void widgetSelected(SelectionEvent e
) {
175 if (isFinished(getProcessStatus())) {
176 ((ProcessEditor
) getEditor()).relaunch();
177 } else if (isRunning(getProcessStatus())) {
178 ((ProcessEditor
) getEditor()).kill();
180 ((ProcessEditor
) getEditor()).process();
184 public void widgetDefaultSelected(SelectionEvent e
) {
189 remove
= tk
.createButton(controls
, null, SWT
.PUSH
);
190 remove
.setImage(SlcImages
.REMOVE_ONE
);
191 remove
.setToolTipText("Remove selected flows");
192 remove
.addSelectionListener(new SelectionListener() {
193 public void widgetSelected(SelectionEvent e
) {
194 removeSelectedFlows();
197 public void widgetDefaultSelected(SelectionEvent e
) {
202 clear
= tk
.createButton(controls
, null, SWT
.PUSH
);
203 clear
.setImage(SlcImages
.REMOVE_ALL
);
204 clear
.setToolTipText("Clear all flows");
205 clear
.addSelectionListener(new SelectionListener() {
206 public void widgetSelected(SelectionEvent e
) {
210 public void widgetDefaultSelected(SelectionEvent e
) {
215 Composite statusComposite
= tk
.createComposite(controls
);
216 RowData rowData
= new RowData();
219 statusComposite
.setLayoutData(rowData
);
220 statusComposite
.setLayout(new FillLayout());
221 statusLabel
= tk
.createLabel(statusComposite
, getProcessStatus());
225 protected void createBuilder(Composite parent
) {
226 FormToolkit tk
= getManagedForm().getToolkit();
227 SashForm sashForm
= new SashForm(parent
, SWT
.HORIZONTAL
);
228 sashForm
.setSashWidth(4);
229 GridData sahFormGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
230 sahFormGd
.widthHint
= 400;
231 sashForm
.setLayoutData(sahFormGd
);
233 Composite flowsComposite
= tk
.createComposite(sashForm
);
234 flowsComposite
.setLayout(new GridLayout(1, false));
236 flowsViewer
= new TreeViewer(flowsComposite
);
237 flowsViewer
.getTree().setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
238 flowsViewer
.setLabelProvider(new FlowsLabelProvider());
239 flowsViewer
.setContentProvider(new FlowsContentProvider());
240 flowsViewer
.addSelectionChangedListener(new FlowsSelectionListener());
242 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
243 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
244 flowsViewer
.addDropSupport(operations
, tt
, new FlowsDropListener(flowsViewer
));
249 flowsViewer
.setInput(getEditorSite());
250 flowsViewer
.setInput(processNode
);
252 Composite valuesComposite
= tk
.createComposite(sashForm
);
253 valuesComposite
.setLayout(new GridLayout(1, false));
255 valuesViewer
= new TableViewer(valuesComposite
);
256 GridData valuedGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
257 // valuedGd.widthHint = 200;
258 valuesViewer
.getTable().setLayoutData(valuedGd
);
259 valuesViewer
.getTable().setHeaderVisible(true);
261 valuesViewer
.setContentProvider(new ValuesContentProvider());
262 initializeValuesViewer(valuesViewer
);
263 sashForm
.setWeights(getWeights());
264 valuesViewer
.setInput(getEditorSite());
267 /** Creates the columns of the values viewer */
268 protected void initializeValuesViewer(TableViewer viewer
) {
269 String
[] titles
= { "Name", "Value" };
270 int[] bounds
= { 200, 100 };
272 for (int i
= 0; i
< titles
.length
; i
++) {
273 TableViewerColumn column
= new TableViewerColumn(viewer
, SWT
.NONE
);
274 column
.getColumn().setText(titles
[i
]);
275 column
.getColumn().setWidth(bounds
[i
]);
276 column
.getColumn().setResizable(true);
277 column
.getColumn().setMoveable(true);
279 column
.setLabelProvider(new ColumnLabelProvider() {
280 public String
getText(Object element
) {
282 Node specAttrNode
= (Node
) element
;
283 return specAttrNode
.getName();
284 } catch (RepositoryException e
) {
285 throw new SlcException("Cannot get value", e
);
290 column
.setLabelProvider(new ColumnLabelProvider() {
291 public String
getText(Object element
) {
292 return getAttributeSpecText((Node
) element
);
295 column
.setEditingSupport(new ValuesEditingSupport(viewer
));
299 Table table
= viewer
.getTable();
300 table
.setHeaderVisible(false);
301 table
.setLinesVisible(true);
304 protected int[] getWeights() {
305 return new int[] { 50, 50 };
311 /** Reflects a status change */
312 protected void statusChanged() {
313 String status
= getProcessStatus();
314 statusLabel
.setText(status
);
315 Boolean isEditable
= isEditable(status
);
316 run
.setEnabled(status
.equals(ExecutionProcess
.RUNNING
) || isEditable
);
317 remove
.setEnabled(isEditable
);
318 clear
.setEnabled(isEditable
);
319 // flowsViewer.getTree().setEnabled(isEditable);
320 if (status
.equals(ExecutionProcess
.RUNNING
)) {
321 run
.setEnabled(true);
322 run
.setImage(SlcImages
.KILL
);
323 run
.setToolTipText("Kill");
324 } else if (isFinished(status
)) {
325 run
.setEnabled(true);
326 run
.setImage(SlcImages
.RELAUNCH
);
327 run
.setToolTipText("Relaunch");
330 if (flowsViewer
!= null)
331 flowsViewer
.refresh();
334 /** Adds initial flows from the editor input if any */
335 protected void addInitialFlows() {
336 for (String path
: ((ProcessEditorInput
) getEditorInput()).getInitialFlowPaths()) {
344 * @param path the path of the flow
346 protected void addFlow(String path
) {
348 Node flowNode
= agentSession
.getNode(path
);
349 Node realizedFlowNode
= processNode
.getNode(SLC_FLOW
).addNode(SLC_FLOW
);
350 realizedFlowNode
.setProperty(SLC_NAME
, flowNode
.getProperty(SLC_NAME
).getString());
351 realizedFlowNode
.addMixin(SlcTypes
.SLC_REALIZED_FLOW
);
352 Node address
= realizedFlowNode
.addNode(SLC_ADDRESS
, NodeType
.NT_ADDRESS
);
353 address
.setProperty(Property
.JCR_PATH
, path
);
355 // copy spec attributes
357 if (flowNode
.hasProperty(SLC_SPEC
)) {
358 Node executionSpecNode
= flowNode
.getProperty(SLC_SPEC
).getNode();
359 specAttrsBase
= executionSpecNode
;
360 String executionSpecName
= executionSpecNode
.getProperty(SLC_NAME
).getString();
361 realizedFlowNode
.setProperty(SLC_SPEC
, executionSpecName
);
363 specAttrsBase
= flowNode
;
365 specAttrs
: for (NodeIterator nit
= specAttrsBase
.getNodes(); nit
.hasNext();) {
366 Node specAttrNode
= nit
.nextNode();
367 String attrName
= specAttrNode
.getName();
368 if (!specAttrNode
.isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
370 Node realizedAttrNode
= realizedFlowNode
.addNode(specAttrNode
.getName());
371 JcrUtils
.copy(specAttrNode
, realizedAttrNode
);
373 // override with flow value
374 if (flowNode
.hasNode(attrName
)) {
375 // assuming this is a primitive
376 Node attrNode
= flowNode
.getNode(attrName
);
377 if (attrNode
.hasProperty(SLC_VALUE
))
378 realizedAttrNode
.setProperty(SLC_VALUE
, attrNode
.getProperty(SLC_VALUE
).getValue());
383 StringBuilder editorTitle
= new StringBuilder();
384 NodeIterator it
= realizedFlowNode
.getParent().getNodes(SLC_FLOW
);
385 while (it
.hasNext()) {
386 Node rFlowNode
= it
.nextNode();
387 String name
= rFlowNode
.getProperty(SLC_NAME
).getString();
388 editorTitle
.append(name
).append(' ');
390 ((ProcessEditor
) getEditor()).setEditorTitle(editorTitle
.toString());
392 flowsViewer
.refresh();
393 formPart
.markDirty();
394 } catch (RepositoryException e
) {
395 throw new SlcException("Cannot add flow " + path
, e
);
399 @SuppressWarnings("unchecked")
400 protected void removeSelectedFlows() {
401 if (!flowsViewer
.getSelection().isEmpty()) {
402 Iterator
<Object
> it
= ((StructuredSelection
) flowsViewer
.getSelection()).iterator();
403 while (it
.hasNext()) {
404 Node node
= (Node
) it
.next();
407 } catch (RepositoryException e
) {
408 throw new SlcException("Cannot remove " + node
, e
);
411 flowsViewer
.refresh();
412 formPart
.markDirty();
416 protected void removeAllFlows() {
418 for (NodeIterator nit
= processNode
.getNode(SLC_FLOW
).getNodes(); nit
.hasNext();) {
419 nit
.nextNode().remove();
421 flowsViewer
.refresh();
422 formPart
.markDirty();
423 } catch (RepositoryException e
) {
424 throw new SlcException("Cannot remove flows from " + processNode
, e
);
428 public void commit(Boolean onSave
) {
430 statusLabel
.setText(getProcessStatus());
431 formPart
.commit(onSave
);
437 protected String
getProcessStatus() {
439 return processNode
.getProperty(SLC_STATUS
).getString();
440 } catch (RepositoryException e
) {
441 throw new SlcException("Cannot retrieve status for " + processNode
, e
);
445 /** Optimization so that we don't call the node each time */
446 protected static Boolean
isEditable(String status
) {
447 return status
.equals(ExecutionProcess
.NEW
) || status
.equals(ExecutionProcess
.INITIALIZED
);
450 protected static Boolean
isFinished(String status
) {
451 return status
.equals(ExecutionProcess
.COMPLETED
) || status
.equals(ExecutionProcess
.ERROR
)
452 || status
.equals(ExecutionProcess
.KILLED
);
455 protected static Boolean
isRunning(String status
) {
456 return status
.equals(ExecutionProcess
.RUNNING
);
463 public void dispose() {
464 JcrUtils
.unregisterQuietly(processNode
, statusObserver
);
465 JcrUtils
.logoutQuietly(agentSession
);
472 protected static String
getAttributeSpecText(Node specAttrNode
) {
474 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
475 if (!specAttrNode
.hasProperty(SLC_VALUE
))
477 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
478 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
))
479 return "****************";
480 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
.getProperty(SLC_VALUE
).getString());
481 return value
.toString();
482 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
483 if (specAttrNode
.hasProperty(SLC_VALUE
)) {
484 int value
= (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
485 NodeIterator children
= specAttrNode
.getNodes();
487 while (children
.hasNext()) {
488 Node child
= children
.nextNode();
490 return child
.getProperty(Property
.JCR_TITLE
).getString();
493 throw new SlcException("No child node with index " + value
+ " for spec attribute " + specAttrNode
);
497 throw new SlcException("Unsupported type for spec attribute " + specAttrNode
);
498 } catch (RepositoryException e
) {
499 throw new SlcException("Cannot get value", e
);
506 class FlowsContentProvider
implements ITreeContentProvider
{
507 public Object
[] getElements(Object obj
) {
508 if (!(obj
instanceof Node
))
509 return new Object
[0];
512 Node node
= (Node
) obj
;
513 List
<Node
> children
= new ArrayList
<Node
>();
514 for (NodeIterator nit
= node
.getNode(SLC_FLOW
).getNodes(); nit
.hasNext();) {
515 Node flowNode
= nit
.nextNode();
516 children
.add(flowNode
);
518 return children
.toArray();
519 } catch (RepositoryException e
) {
520 throw new SlcException("Cannot list flows of " + obj
, e
);
524 public void inputChanged(Viewer arg0
, Object arg1
, Object arg2
) {
527 public void dispose() {
530 public Object
[] getChildren(Object parentElement
) {
531 // no children for the time being
535 public Object
getParent(Object element
) {
539 public boolean hasChildren(Object element
) {
545 static class FlowsLabelProvider
extends ColumnLabelProvider
{
547 public String
getText(Object element
) {
548 Node node
= (Node
) element
;
550 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
551 if (node
.hasNode(SLC_ADDRESS
)) {
552 String path
= node
.getNode(SLC_ADDRESS
).getProperty(Property
.JCR_PATH
).getString();
553 String executionModuleName
= SlcJcrUtils
.moduleName(path
);
554 // Node executionModuleNode = node.getSession().getNode(
555 // SlcJcrUtils.modulePath(path));
556 // String executionModuleName = executionModuleNode
557 // .getProperty(SLC_NAME).getString();
558 return executionModuleName
+ ":" + SlcJcrUtils
.flowRelativePath(path
);
561 } catch (RepositoryException e
) {
562 throw new SlcException("Cannot display " + element
, e
);
564 return super.getText(element
);
568 public Image
getImage(Object element
) {
569 Node node
= (Node
) element
;
571 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
572 if (node
.hasProperty(SLC_STATUS
)) {
573 String status
= node
.getProperty(SLC_STATUS
).getString();
574 // TODO: factorize with process view ?
575 if (status
.equals(ExecutionProcess
.RUNNING
))
576 return SlcImages
.PROCESS_RUNNING
;
577 else if (status
.equals(ExecutionProcess
.ERROR
) || status
.equals(ExecutionProcess
.KILLED
))
578 return SlcImages
.PROCESS_ERROR
;
579 else if (status
.equals(ExecutionProcess
.COMPLETED
))
580 return SlcImages
.PROCESS_COMPLETED
;
582 return SlcImages
.FLOW
;
584 } catch (RepositoryException e
) {
585 throw new SlcException("Cannot display " + element
, e
);
587 return super.getImage(element
);
592 /** Parameter view is updated each time a new line is selected */
593 class FlowsSelectionListener
implements ISelectionChangedListener
{
594 public void selectionChanged(SelectionChangedEvent evt
) {
595 if (evt
.getSelection().isEmpty()) {
596 valuesViewer
.setInput(getEditorSite());
599 Node realizedFlowNode
= (Node
) ((IStructuredSelection
) evt
.getSelection()).getFirstElement();
600 valuesViewer
.setInput(realizedFlowNode
);
605 * Add a context menu that call private methods. It only relies on selected
606 * item(s) not on parameter that are passed in the menuAboutToShow method
608 private void addContextMenu() {
609 Menu menu
= new Menu(flowsViewer
.getControl());
611 MenuItem removeItems
= new MenuItem(menu
, SWT
.PUSH
);
612 removeItems
.addSelectionListener(new SelectionListener() {
614 public void widgetSelected(SelectionEvent e
) {
615 removeSelectedFlows();
618 public void widgetDefaultSelected(SelectionEvent e
) {
621 removeItems
.setText("Remove selected flow(s)");
623 MenuItem removeAllItems
= new MenuItem(menu
, SWT
.PUSH
);
624 removeAllItems
.addSelectionListener(new SelectionListener() {
626 public void widgetSelected(SelectionEvent e
) {
630 public void widgetDefaultSelected(SelectionEvent e
) {
633 removeAllItems
.setText("Remove all flows");
634 flowsViewer
.getTree().setMenu(menu
);
637 /** Manages drop event. */
638 class FlowsDropListener
extends ViewerDropAdapter
{
640 public FlowsDropListener(Viewer viewer
) {
645 public boolean performDrop(Object data
) {
647 // Parse the received String, paths are separated with a carriage
649 String
[] paths
= data
.toString().split(new String("\n"));
650 SortedSet
<String
> resultPaths
= new TreeSet
<String
>();
651 for (String path
: paths
) {
653 // either a node or a whole directory can have been dragged
654 QueryManager qm
= processNode
.getSession().getWorkspace().getQueryManager();
655 String statement
= "SELECT * FROM [" + SlcTypes
.SLC_EXECUTION_FLOW
+ "] WHERE ISDESCENDANTNODE(['"
656 + path
+ "']) OR ISSAMENODE(['" + path
+ "'])";
657 Query query
= qm
.createQuery(statement
, Query
.JCR_SQL2
);
660 for (NodeIterator nit
= query
.execute().getNodes(); nit
.hasNext();) {
661 String currPath
= nit
.nextNode().getPath();
662 // do not add twice a same flow
663 if (!resultPaths
.contains(currPath
))
664 resultPaths
.add(currPath
);
666 } catch (RepositoryException e
) {
667 throw new SlcException("Cannot query flows under " + path
, e
);
670 for (String p
: resultPaths
) {
678 public boolean validateDrop(Object target
, int operation
, TransferData transferType
) {
679 return isEditable(getProcessStatus());
686 static class ValuesContentProvider
implements IStructuredContentProvider
{
688 public Object
[] getElements(Object inputElement
) {
689 if (!(inputElement
instanceof Node
))
690 return new Object
[0];
693 Node realizedFlowNode
= (Node
) inputElement
;
694 List
<Node
> specAttributes
= new ArrayList
<Node
>();
695 specAttrs
: for (NodeIterator nit
= realizedFlowNode
.getNodes(); nit
.hasNext();) {
696 Node specAttrNode
= nit
.nextNode();
697 if (!specAttrNode
.isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
699 // workaround to enable hiding of necessary but unusable
701 else if (specAttrNode
.hasProperty(SlcNames
.SLC_IS_HIDDEN
)
702 && specAttrNode
.getProperty(SlcNames
.SLC_IS_HIDDEN
).getBoolean())
704 specAttributes
.add(specAttrNode
);
706 return specAttributes
.toArray();
707 } catch (RepositoryException e
) {
708 throw new SlcException("Cannot get elements", e
);
712 public void dispose() {
715 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
719 class ValuesEditingSupport
extends EditingSupport
{
720 private final TableViewer tableViewer
;
722 public ValuesEditingSupport(ColumnViewer viewer
) {
724 tableViewer
= (TableViewer
) viewer
;
728 protected CellEditor
getCellEditor(Object element
) {
730 Node specAttrNode
= (Node
) element
;
731 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
732 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
733 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
)) {
734 return new TextCellEditor(tableViewer
.getTable(), SWT
.PASSWORD
);
736 return new TextCellEditor(tableViewer
.getTable());
738 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
739 NodeIterator children
= specAttrNode
.getNodes();
740 ArrayList
<String
> items
= new ArrayList
<String
>();
741 while (children
.hasNext()) {
742 Node child
= children
.nextNode();
743 if (child
.isNodeType(NodeType
.MIX_TITLE
))
744 items
.add(child
.getProperty(Property
.JCR_TITLE
).getString());
746 return new ComboBoxCellEditor(tableViewer
.getTable(), items
.toArray(new String
[items
.size()]));
749 } catch (RepositoryException e
) {
750 throw new SlcException("Cannot get cell editor", e
);
755 protected boolean canEdit(Object element
) {
757 Node specAttrNode
= (Node
) element
;
758 Boolean cannotEdit
= specAttrNode
.getProperty(SLC_IS_IMMUTABLE
).getBoolean()
759 || specAttrNode
.getProperty(SLC_IS_CONSTANT
).getBoolean();
760 return !cannotEdit
&& isSupportedAttributeType(specAttrNode
);
761 } catch (RepositoryException e
) {
762 throw new SlcException("Cannot check whether " + element
+ " is editable", e
);
767 * Supports {@link SlcTypes#SLC_PRIMITIVE_SPEC_ATTRIBUTE} and
768 * {@link SlcTypes#SLC_REF_SPEC_ATTRIBUTE}
770 protected boolean isSupportedAttributeType(Node specAttrNode
) throws RepositoryException
{
771 return specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)
772 || specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
);
776 protected Object
getValue(Object element
) {
777 Node specAttrNode
= (Node
) element
;
779 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
780 if (!specAttrNode
.hasProperty(SLC_VALUE
))
782 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
783 // TODO optimize based on data type?
784 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
.getProperty(SLC_VALUE
).getString());
785 return value
.toString();
786 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
787 if (!specAttrNode
.hasProperty(SLC_VALUE
))
789 // return the index of the sub node as set by setValue()
790 // in the future we may manage references as well
791 return (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
793 throw new SlcException("Unsupported type for spec attribute " + specAttrNode
);
794 } catch (RepositoryException e
) {
795 throw new SlcException("Cannot get value for " + element
, e
);
800 protected void setValue(Object element
, Object value
) {
802 Node specAttrNode
= (Node
) element
;
803 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
804 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
805 SlcJcrUtils
.setPrimitiveAsProperty(specAttrNode
, SLC_VALUE
, type
, value
);
806 valuesViewer
.refresh();
807 formPart
.markDirty();
808 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
809 specAttrNode
.setProperty(SLC_VALUE
, ((Integer
) value
).longValue());
810 valuesViewer
.refresh();
811 formPart
.markDirty();
813 } catch (RepositoryException e
) {
814 throw new SlcException("Cannot get celle editor", e
);