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
.Node
;
25 import javax
.jcr
.NodeIterator
;
26 import javax
.jcr
.Property
;
27 import javax
.jcr
.RepositoryException
;
28 import javax
.jcr
.nodetype
.NodeType
;
29 import javax
.jcr
.observation
.Event
;
30 import javax
.jcr
.observation
.EventListener
;
31 import javax
.jcr
.observation
.ObservationManager
;
32 import javax
.jcr
.query
.Query
;
33 import javax
.jcr
.query
.QueryManager
;
35 import org
.argeo
.ArgeoException
;
36 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
37 import org
.argeo
.jcr
.JcrUtils
;
38 import org
.argeo
.slc
.SlcException
;
39 import org
.argeo
.slc
.client
.ui
.SlcImages
;
40 import org
.argeo
.slc
.core
.execution
.PrimitiveAccessor
;
41 import org
.argeo
.slc
.core
.execution
.PrimitiveUtils
;
42 import org
.argeo
.slc
.execution
.ExecutionProcess
;
43 import org
.argeo
.slc
.jcr
.SlcJcrUtils
;
44 import org
.argeo
.slc
.jcr
.SlcNames
;
45 import org
.argeo
.slc
.jcr
.SlcTypes
;
46 import org
.eclipse
.jface
.viewers
.CellEditor
;
47 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
48 import org
.eclipse
.jface
.viewers
.ColumnViewer
;
49 import org
.eclipse
.jface
.viewers
.ComboBoxCellEditor
;
50 import org
.eclipse
.jface
.viewers
.EditingSupport
;
51 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
52 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
53 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
54 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
55 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
56 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
57 import org
.eclipse
.jface
.viewers
.TableViewer
;
58 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
59 import org
.eclipse
.jface
.viewers
.TextCellEditor
;
60 import org
.eclipse
.jface
.viewers
.TreeViewer
;
61 import org
.eclipse
.jface
.viewers
.Viewer
;
62 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
63 import org
.eclipse
.swt
.SWT
;
64 import org
.eclipse
.swt
.custom
.SashForm
;
65 import org
.eclipse
.swt
.dnd
.DND
;
66 import org
.eclipse
.swt
.dnd
.TextTransfer
;
67 import org
.eclipse
.swt
.dnd
.Transfer
;
68 import org
.eclipse
.swt
.dnd
.TransferData
;
69 import org
.eclipse
.swt
.events
.SelectionEvent
;
70 import org
.eclipse
.swt
.events
.SelectionListener
;
71 import org
.eclipse
.swt
.graphics
.Image
;
72 import org
.eclipse
.swt
.layout
.FillLayout
;
73 import org
.eclipse
.swt
.layout
.GridData
;
74 import org
.eclipse
.swt
.layout
.GridLayout
;
75 import org
.eclipse
.swt
.layout
.RowData
;
76 import org
.eclipse
.swt
.layout
.RowLayout
;
77 import org
.eclipse
.swt
.widgets
.Button
;
78 import org
.eclipse
.swt
.widgets
.Composite
;
79 import org
.eclipse
.swt
.widgets
.Label
;
80 import org
.eclipse
.swt
.widgets
.Menu
;
81 import org
.eclipse
.swt
.widgets
.MenuItem
;
82 import org
.eclipse
.swt
.widgets
.Table
;
83 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
84 import org
.eclipse
.ui
.forms
.IManagedForm
;
85 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
86 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
87 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
89 /** Definition of the process. */
90 public class ProcessBuilderPage
extends FormPage
implements SlcNames
{
91 // private final static Log log =
92 // LogFactory.getLog(ProcessBuilderPage.class);
94 public final static String ID
= "processBuilderPage";
96 /** To be displayed in empty lists */
97 final static String NONE
= "<none>";
99 private Node processNode
;
101 private TreeViewer flowsViewer
;
102 private TableViewer valuesViewer
;
103 private Label statusLabel
;
105 private Button remove
;
106 private Button clear
;
108 private AbstractFormPart formPart
;
109 private EventListener statusObserver
;
111 public ProcessBuilderPage(ProcessEditor editor
, Node processNode
) {
112 super(editor
, ID
, "Definition");
113 this.processNode
= processNode
;
117 protected void createFormContent(IManagedForm mf
) {
119 ScrolledForm form
= mf
.getForm();
120 form
.setExpandHorizontal(true);
121 form
.setExpandVertical(true);
122 form
.setText("Process " + processNode
.getName());
123 GridLayout mainLayout
= new GridLayout(1, true);
124 form
.getBody().setLayout(mainLayout
);
126 createControls(form
.getBody());
127 createBuilder(form
.getBody());
130 formPart
= new AbstractFormPart() {
133 getManagedForm().addPart(formPart
);
136 statusObserver
= new AsyncUiEventListener(form
.getDisplay()) {
137 protected void onEventInUiThread(List
<Event
> events
) {
141 ObservationManager observationManager
= processNode
.getSession()
142 .getWorkspace().getObservationManager();
143 observationManager
.addEventListener(statusObserver
,
144 Event
.PROPERTY_CHANGED
, processNode
.getPath(), true, null,
147 // make sure all controls are in line with status
153 } catch (RepositoryException e
) {
154 throw new ArgeoException("Cannot create form content", e
);
158 protected void createControls(Composite parent
) {
159 FormToolkit tk
= getManagedForm().getToolkit();
161 Composite controls
= tk
.createComposite(parent
);
162 controls
.setLayout(new RowLayout());
163 controls
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
165 run
= tk
.createButton(controls
, null, SWT
.PUSH
);
166 run
.setToolTipText("Run");
167 run
.setImage(SlcImages
.LAUNCH
);
168 run
.addSelectionListener(new SelectionListener() {
169 public void widgetSelected(SelectionEvent e
) {
170 if (isFinished(getProcessStatus())) {
171 ((ProcessEditor
) getEditor()).relaunch();
172 } else if (isRunning(getProcessStatus())) {
173 ((ProcessEditor
) getEditor()).kill();
175 ((ProcessEditor
) getEditor()).process();
179 public void widgetDefaultSelected(SelectionEvent e
) {
184 remove
= tk
.createButton(controls
, null, SWT
.PUSH
);
185 remove
.setImage(SlcImages
.REMOVE_ONE
);
186 remove
.setToolTipText("Remove selected flows");
187 remove
.addSelectionListener(new SelectionListener() {
188 public void widgetSelected(SelectionEvent e
) {
189 removeSelectedFlows();
192 public void widgetDefaultSelected(SelectionEvent e
) {
197 clear
= tk
.createButton(controls
, null, SWT
.PUSH
);
198 clear
.setImage(SlcImages
.REMOVE_ALL
);
199 clear
.setToolTipText("Clear all flows");
200 clear
.addSelectionListener(new SelectionListener() {
201 public void widgetSelected(SelectionEvent e
) {
205 public void widgetDefaultSelected(SelectionEvent e
) {
210 Composite statusComposite
= tk
.createComposite(controls
);
211 RowData rowData
= new RowData();
214 statusComposite
.setLayoutData(rowData
);
215 statusComposite
.setLayout(new FillLayout());
216 statusLabel
= tk
.createLabel(statusComposite
, getProcessStatus());
220 protected void createBuilder(Composite parent
) {
221 FormToolkit tk
= getManagedForm().getToolkit();
222 SashForm sashForm
= new SashForm(parent
, SWT
.HORIZONTAL
);
223 sashForm
.setSashWidth(4);
224 GridData sahFormGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
225 sahFormGd
.widthHint
= 400;
226 sashForm
.setLayoutData(sahFormGd
);
228 Composite flowsComposite
= tk
.createComposite(sashForm
);
229 flowsComposite
.setLayout(new GridLayout(1, false));
231 flowsViewer
= new TreeViewer(flowsComposite
);
232 flowsViewer
.getTree().setLayoutData(
233 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
234 flowsViewer
.setLabelProvider(new FlowsLabelProvider());
235 flowsViewer
.setContentProvider(new FlowsContentProvider());
236 flowsViewer
.addSelectionChangedListener(new FlowsSelectionListener());
238 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
239 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
240 flowsViewer
.addDropSupport(operations
, tt
, new FlowsDropListener(
246 flowsViewer
.setInput(getEditorSite());
247 flowsViewer
.setInput(processNode
);
249 Composite valuesComposite
= tk
.createComposite(sashForm
);
250 valuesComposite
.setLayout(new GridLayout(1, false));
252 valuesViewer
= new TableViewer(valuesComposite
);
253 GridData valuedGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
254 // valuedGd.widthHint = 200;
255 valuesViewer
.getTable().setLayoutData(valuedGd
);
256 valuesViewer
.getTable().setHeaderVisible(true);
258 valuesViewer
.setContentProvider(new ValuesContentProvider());
259 initializeValuesViewer(valuesViewer
);
260 sashForm
.setWeights(getWeights());
261 valuesViewer
.setInput(getEditorSite());
264 /** Creates the columns of the values viewer */
265 protected void initializeValuesViewer(TableViewer viewer
) {
266 String
[] titles
= { "Name", "Value" };
267 int[] bounds
= { 200, 100 };
269 for (int i
= 0; i
< titles
.length
; i
++) {
270 TableViewerColumn column
= new TableViewerColumn(viewer
, SWT
.NONE
);
271 column
.getColumn().setText(titles
[i
]);
272 column
.getColumn().setWidth(bounds
[i
]);
273 column
.getColumn().setResizable(true);
274 column
.getColumn().setMoveable(true);
276 column
.setLabelProvider(new ColumnLabelProvider() {
277 public String
getText(Object element
) {
279 Node specAttrNode
= (Node
) element
;
280 return specAttrNode
.getName();
281 } catch (RepositoryException e
) {
282 throw new SlcException("Cannot get value", e
);
287 column
.setLabelProvider(new ColumnLabelProvider() {
288 public String
getText(Object element
) {
289 return getAttributeSpecText((Node
) element
);
292 column
.setEditingSupport(new ValuesEditingSupport(viewer
));
296 Table table
= viewer
.getTable();
297 table
.setHeaderVisible(false);
298 table
.setLinesVisible(true);
301 protected int[] getWeights() {
302 return new int[] { 50, 50 };
308 /** Reflects a status change */
309 protected void statusChanged() {
310 String status
= getProcessStatus();
311 statusLabel
.setText(status
);
312 Boolean isEditable
= isEditable(status
);
313 run
.setEnabled(status
.equals(ExecutionProcess
.RUNNING
) || isEditable
);
314 remove
.setEnabled(isEditable
);
315 clear
.setEnabled(isEditable
);
316 // flowsViewer.getTree().setEnabled(isEditable);
317 if (status
.equals(ExecutionProcess
.RUNNING
)) {
318 run
.setEnabled(true);
319 run
.setImage(SlcImages
.KILL
);
320 run
.setToolTipText("Kill");
321 } else if (isFinished(status
)) {
322 run
.setEnabled(true);
323 run
.setImage(SlcImages
.RELAUNCH
);
324 run
.setToolTipText("Relaunch");
327 if (flowsViewer
!= null)
328 flowsViewer
.refresh();
331 /** Adds initial flows from the editor input if any */
332 protected void addInitialFlows() {
333 for (String path
: ((ProcessEditorInput
) getEditorInput())
334 .getInitialFlowPaths()) {
343 * the path of the flow
345 protected void addFlow(String path
) {
347 Node flowNode
= processNode
.getSession().getNode(path
);
348 Node realizedFlowNode
= processNode
.getNode(SLC_FLOW
).addNode(
350 realizedFlowNode
.setProperty(SLC_NAME
,
351 flowNode
.getProperty(SLC_NAME
).getString());
352 realizedFlowNode
.addMixin(SlcTypes
.SLC_REALIZED_FLOW
);
353 Node address
= realizedFlowNode
.addNode(SLC_ADDRESS
,
354 NodeType
.NT_ADDRESS
);
355 address
.setProperty(Property
.JCR_PATH
, path
);
357 // copy spec attributes
359 if (flowNode
.hasProperty(SLC_SPEC
)) {
360 Node executionSpecNode
= flowNode
.getProperty(SLC_SPEC
)
362 specAttrsBase
= executionSpecNode
;
363 String executionSpecName
= executionSpecNode
.getProperty(
364 SLC_NAME
).getString();
365 realizedFlowNode
.setProperty(SLC_SPEC
, executionSpecName
);
367 specAttrsBase
= flowNode
;
369 specAttrs
: for (NodeIterator nit
= specAttrsBase
.getNodes(); nit
371 Node specAttrNode
= nit
.nextNode();
372 String attrName
= specAttrNode
.getName();
374 .isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
376 Node realizedAttrNode
= realizedFlowNode
.addNode(specAttrNode
378 JcrUtils
.copy(specAttrNode
, realizedAttrNode
);
380 // override with flow value
381 if (flowNode
.hasNode(attrName
)) {
382 // assuming this is a primitive
383 Node attrNode
= flowNode
.getNode(attrName
);
384 if (attrNode
.hasProperty(SLC_VALUE
))
385 realizedAttrNode
.setProperty(SLC_VALUE
, attrNode
386 .getProperty(SLC_VALUE
).getValue());
391 StringBuilder editorTitle
= new StringBuilder();
392 NodeIterator it
= realizedFlowNode
.getParent().getNodes(SLC_FLOW
);
393 while (it
.hasNext()) {
394 Node rFlowNode
= it
.nextNode();
395 String name
= rFlowNode
.getProperty(SLC_NAME
).getString();
396 editorTitle
.append(name
).append(' ');
398 ((ProcessEditor
) getEditor())
399 .setEditorTitle(editorTitle
.toString());
401 flowsViewer
.refresh();
402 formPart
.markDirty();
403 } catch (RepositoryException e
) {
404 throw new SlcException("Cannot add flow " + path
, e
);
408 @SuppressWarnings("unchecked")
409 protected void removeSelectedFlows() {
410 if (!flowsViewer
.getSelection().isEmpty()) {
411 Iterator
<Object
> it
= ((StructuredSelection
) flowsViewer
412 .getSelection()).iterator();
413 while (it
.hasNext()) {
414 Node node
= (Node
) it
.next();
417 } catch (RepositoryException e
) {
418 throw new ArgeoException("Cannot remove " + node
, e
);
421 flowsViewer
.refresh();
422 formPart
.markDirty();
426 protected void removeAllFlows() {
428 for (NodeIterator nit
= processNode
.getNode(SLC_FLOW
).getNodes(); nit
430 nit
.nextNode().remove();
432 flowsViewer
.refresh();
433 formPart
.markDirty();
434 } catch (RepositoryException e
) {
435 throw new ArgeoException("Cannot remove flows from " + processNode
,
440 public void commit(Boolean onSave
) {
442 statusLabel
.setText(getProcessStatus());
443 formPart
.commit(onSave
);
449 protected String
getProcessStatus() {
451 return processNode
.getProperty(SLC_STATUS
).getString();
452 } catch (RepositoryException e
) {
453 throw new SlcException("Cannot retrieve status for " + processNode
,
458 /** Optimization so that we don't call the node each time */
459 protected static Boolean
isEditable(String status
) {
460 return status
.equals(ExecutionProcess
.NEW
)
461 || status
.equals(ExecutionProcess
.INITIALIZED
);
464 protected static Boolean
isFinished(String status
) {
465 return status
.equals(ExecutionProcess
.COMPLETED
)
466 || status
.equals(ExecutionProcess
.ERROR
)
467 || status
.equals(ExecutionProcess
.KILLED
);
470 protected static Boolean
isRunning(String status
) {
471 return status
.equals(ExecutionProcess
.RUNNING
);
478 public void dispose() {
479 JcrUtils
.unregisterQuietly(processNode
, statusObserver
);
486 protected static String
getAttributeSpecText(Node specAttrNode
) {
488 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
489 if (!specAttrNode
.hasProperty(SLC_VALUE
))
491 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
492 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
))
493 return "****************";
494 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
495 .getProperty(SLC_VALUE
).getString());
496 return value
.toString();
497 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
498 if (specAttrNode
.hasProperty(SLC_VALUE
)) {
499 int value
= (int) specAttrNode
.getProperty(SLC_VALUE
)
501 NodeIterator children
= specAttrNode
.getNodes();
503 while (children
.hasNext()) {
504 Node child
= children
.nextNode();
506 return child
.getProperty(Property
.JCR_TITLE
)
510 throw new SlcException("No child node with index " + value
511 + " for spec attribute " + specAttrNode
);
515 throw new SlcException("Unsupported type for spec attribute "
517 } catch (RepositoryException e
) {
518 throw new SlcException("Cannot get value", e
);
525 class FlowsContentProvider
implements ITreeContentProvider
{
526 public Object
[] getElements(Object obj
) {
527 if (!(obj
instanceof Node
))
528 return new Object
[0];
531 Node node
= (Node
) obj
;
532 List
<Node
> children
= new ArrayList
<Node
>();
533 for (NodeIterator nit
= node
.getNode(SLC_FLOW
).getNodes(); nit
535 Node flowNode
= nit
.nextNode();
536 children
.add(flowNode
);
538 return children
.toArray();
539 } catch (RepositoryException e
) {
540 throw new SlcException("Cannot list flows of " + obj
, e
);
544 public void inputChanged(Viewer arg0
, Object arg1
, Object arg2
) {
547 public void dispose() {
550 public Object
[] getChildren(Object parentElement
) {
551 // no children for the time being
555 public Object
getParent(Object element
) {
559 public boolean hasChildren(Object element
) {
565 static class FlowsLabelProvider
extends ColumnLabelProvider
{
567 public String
getText(Object element
) {
568 Node node
= (Node
) element
;
570 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
571 if (node
.hasNode(SLC_ADDRESS
)) {
572 String path
= node
.getNode(SLC_ADDRESS
)
573 .getProperty(Property
.JCR_PATH
).getString();
574 String executionModuleName
= SlcJcrUtils
576 // Node executionModuleNode = node.getSession().getNode(
577 // SlcJcrUtils.modulePath(path));
578 // String executionModuleName = executionModuleNode
579 // .getProperty(SLC_NAME).getString();
580 return executionModuleName
+ ":"
581 + SlcJcrUtils
.flowRelativePath(path
);
584 } catch (RepositoryException e
) {
585 throw new SlcException("Cannot display " + element
, e
);
587 return super.getText(element
);
591 public Image
getImage(Object element
) {
592 Node node
= (Node
) element
;
594 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
595 if (node
.hasProperty(SLC_STATUS
)) {
596 String status
= node
.getProperty(SLC_STATUS
)
598 // TODO: factorize with process view ?
599 if (status
.equals(ExecutionProcess
.RUNNING
))
600 return SlcImages
.PROCESS_RUNNING
;
601 else if (status
.equals(ExecutionProcess
.ERROR
)
602 || status
.equals(ExecutionProcess
.KILLED
))
603 return SlcImages
.PROCESS_ERROR
;
604 else if (status
.equals(ExecutionProcess
.COMPLETED
))
605 return SlcImages
.PROCESS_COMPLETED
;
607 return SlcImages
.FLOW
;
609 } catch (RepositoryException e
) {
610 throw new SlcException("Cannot display " + element
, e
);
612 return super.getImage(element
);
617 /** Parameter view is updated each time a new line is selected */
618 class FlowsSelectionListener
implements ISelectionChangedListener
{
619 public void selectionChanged(SelectionChangedEvent evt
) {
620 if (evt
.getSelection().isEmpty()) {
621 valuesViewer
.setInput(getEditorSite());
624 Node realizedFlowNode
= (Node
) ((IStructuredSelection
) evt
625 .getSelection()).getFirstElement();
626 valuesViewer
.setInput(realizedFlowNode
);
631 * Add a context menu that call private methods. It only relies on selected
632 * item(s) not on parameter that are passed in the menuAboutToShow method
634 private void addContextMenu() {
635 Menu menu
= new Menu(flowsViewer
.getControl());
637 MenuItem removeItems
= new MenuItem(menu
, SWT
.PUSH
);
638 removeItems
.addSelectionListener(new SelectionListener() {
640 public void widgetSelected(SelectionEvent e
) {
641 removeSelectedFlows();
644 public void widgetDefaultSelected(SelectionEvent e
) {
647 removeItems
.setText("Remove selected flow(s)");
649 MenuItem removeAllItems
= new MenuItem(menu
, SWT
.PUSH
);
650 removeAllItems
.addSelectionListener(new SelectionListener() {
652 public void widgetSelected(SelectionEvent e
) {
656 public void widgetDefaultSelected(SelectionEvent e
) {
659 removeAllItems
.setText("Remove all flows");
660 flowsViewer
.getTree().setMenu(menu
);
663 /** Manages drop event. */
664 class FlowsDropListener
extends ViewerDropAdapter
{
666 public FlowsDropListener(Viewer viewer
) {
671 public boolean performDrop(Object data
) {
673 // Parse the received String, paths are separated with a carriage
675 String
[] paths
= data
.toString().split(new String("\n"));
676 SortedSet
<String
> resultPaths
= new TreeSet
<String
>();
677 for (String path
: paths
) {
679 // either a node or a whole directory can have been dragged
680 QueryManager qm
= processNode
.getSession().getWorkspace()
682 String statement
= "SELECT * FROM ["
683 + SlcTypes
.SLC_EXECUTION_FLOW
684 + "] WHERE ISDESCENDANTNODE(['" + path
685 + "']) OR ISSAMENODE(['" + path
+ "'])";
686 Query query
= qm
.createQuery(statement
, Query
.JCR_SQL2
);
689 for (NodeIterator nit
= query
.execute().getNodes(); nit
691 String currPath
= nit
.nextNode().getPath();
692 // do not add twice a same flow
693 if (!resultPaths
.contains(currPath
))
694 resultPaths
.add(currPath
);
696 } catch (RepositoryException e
) {
697 throw new SlcException("Cannot query flows under " + path
,
701 for (String p
: resultPaths
) {
709 public boolean validateDrop(Object target
, int operation
,
710 TransferData transferType
) {
711 return isEditable(getProcessStatus());
718 static class ValuesContentProvider
implements IStructuredContentProvider
{
720 public Object
[] getElements(Object inputElement
) {
721 if (!(inputElement
instanceof Node
))
722 return new Object
[0];
725 Node realizedFlowNode
= (Node
) inputElement
;
726 List
<Node
> specAttributes
= new ArrayList
<Node
>();
727 specAttrs
: for (NodeIterator nit
= realizedFlowNode
.getNodes(); nit
729 Node specAttrNode
= nit
.nextNode();
731 .isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
733 // workaround to enable hiding of necessary but unusable
735 else if (specAttrNode
.hasProperty(SlcNames
.SLC_IS_HIDDEN
)
736 && specAttrNode
.getProperty(SlcNames
.SLC_IS_HIDDEN
)
739 specAttributes
.add(specAttrNode
);
741 return specAttributes
.toArray();
742 } catch (RepositoryException e
) {
743 throw new SlcException("Cannot get elements", e
);
747 public void dispose() {
750 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
754 class ValuesEditingSupport
extends EditingSupport
{
755 private final TableViewer tableViewer
;
757 public ValuesEditingSupport(ColumnViewer viewer
) {
759 tableViewer
= (TableViewer
) viewer
;
763 protected CellEditor
getCellEditor(Object element
) {
765 Node specAttrNode
= (Node
) element
;
767 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
768 String type
= specAttrNode
.getProperty(SLC_TYPE
)
770 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
)) {
771 return new TextCellEditor(tableViewer
.getTable(),
774 return new TextCellEditor(tableViewer
.getTable());
776 } else if (specAttrNode
777 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
778 NodeIterator children
= specAttrNode
.getNodes();
779 ArrayList
<String
> items
= new ArrayList
<String
>();
780 while (children
.hasNext()) {
781 Node child
= children
.nextNode();
782 if (child
.isNodeType(NodeType
.MIX_TITLE
))
783 items
.add(child
.getProperty(Property
.JCR_TITLE
)
786 return new ComboBoxCellEditor(tableViewer
.getTable(),
787 items
.toArray(new String
[items
.size()]));
790 } catch (RepositoryException e
) {
791 throw new SlcException("Cannot get cell editor", e
);
796 protected boolean canEdit(Object element
) {
798 Node specAttrNode
= (Node
) element
;
799 Boolean cannotEdit
= specAttrNode
.getProperty(SLC_IS_IMMUTABLE
)
801 || specAttrNode
.getProperty(SLC_IS_CONSTANT
)
803 return !cannotEdit
&& isSupportedAttributeType(specAttrNode
);
804 } catch (RepositoryException e
) {
805 throw new SlcException("Cannot check whether " + element
806 + " is editable", e
);
811 * Supports {@link SlcTypes#SLC_PRIMITIVE_SPEC_ATTRIBUTE} and
812 * {@link SlcTypes#SLC_REF_SPEC_ATTRIBUTE}
814 protected boolean isSupportedAttributeType(Node specAttrNode
)
815 throws RepositoryException
{
817 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)
818 || specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
);
822 protected Object
getValue(Object element
) {
823 Node specAttrNode
= (Node
) element
;
826 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
827 if (!specAttrNode
.hasProperty(SLC_VALUE
))
829 String type
= specAttrNode
.getProperty(SLC_TYPE
)
831 // TODO optimize based on data type?
832 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
833 .getProperty(SLC_VALUE
).getString());
834 return value
.toString();
835 } else if (specAttrNode
836 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
837 if (!specAttrNode
.hasProperty(SLC_VALUE
))
839 // return the index of the sub node as set by setValue()
840 // in the future we may manage references as well
841 return (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
843 throw new SlcException("Unsupported type for spec attribute "
845 } catch (RepositoryException e
) {
846 throw new SlcException("Cannot get value for " + element
, e
);
851 protected void setValue(Object element
, Object value
) {
853 Node specAttrNode
= (Node
) element
;
855 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
856 String type
= specAttrNode
.getProperty(SLC_TYPE
)
858 SlcJcrUtils
.setPrimitiveAsProperty(specAttrNode
, SLC_VALUE
,
860 valuesViewer
.refresh();
861 formPart
.markDirty();
862 } else if (specAttrNode
863 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
864 specAttrNode
.setProperty(SLC_VALUE
,
865 ((Integer
) value
).longValue());
866 valuesViewer
.refresh();
867 formPart
.markDirty();
869 } catch (RepositoryException e
) {
870 throw new SlcException("Cannot get celle editor", e
);