1 package org
.argeo
.slc
.client
.ui
.editors
;
3 import java
.util
.ArrayList
;
4 import java
.util
.Iterator
;
6 import java
.util
.SortedSet
;
7 import java
.util
.TreeSet
;
9 import javax
.jcr
.LoginException
;
10 import javax
.jcr
.Node
;
11 import javax
.jcr
.NodeIterator
;
12 import javax
.jcr
.Property
;
13 import javax
.jcr
.RepositoryException
;
14 import javax
.jcr
.Session
;
15 import javax
.jcr
.nodetype
.NodeType
;
16 import javax
.jcr
.observation
.Event
;
17 import javax
.jcr
.observation
.EventListener
;
18 import javax
.jcr
.observation
.ObservationManager
;
19 import javax
.jcr
.query
.Query
;
20 import javax
.jcr
.query
.QueryManager
;
22 import org
.argeo
.eclipse
.ui
.jcr
.AsyncUiEventListener
;
23 import org
.argeo
.jcr
.JcrUtils
;
24 import org
.argeo
.slc
.SlcException
;
25 import org
.argeo
.slc
.SlcNames
;
26 import org
.argeo
.slc
.SlcTypes
;
27 import org
.argeo
.slc
.client
.ui
.SlcImages
;
28 import org
.argeo
.slc
.execution
.ExecutionProcess
;
29 import org
.argeo
.slc
.jcr
.SlcJcrUtils
;
30 import org
.argeo
.slc
.primitive
.PrimitiveAccessor
;
31 import org
.argeo
.slc
.primitive
.PrimitiveUtils
;
32 import org
.eclipse
.jface
.viewers
.CellEditor
;
33 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
34 import org
.eclipse
.jface
.viewers
.ColumnViewer
;
35 import org
.eclipse
.jface
.viewers
.ComboBoxCellEditor
;
36 import org
.eclipse
.jface
.viewers
.EditingSupport
;
37 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
38 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
39 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
40 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
41 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
42 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
43 import org
.eclipse
.jface
.viewers
.TableViewer
;
44 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
45 import org
.eclipse
.jface
.viewers
.TextCellEditor
;
46 import org
.eclipse
.jface
.viewers
.TreeViewer
;
47 import org
.eclipse
.jface
.viewers
.Viewer
;
48 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
49 import org
.eclipse
.swt
.SWT
;
50 import org
.eclipse
.swt
.custom
.SashForm
;
51 import org
.eclipse
.swt
.dnd
.DND
;
52 import org
.eclipse
.swt
.dnd
.TextTransfer
;
53 import org
.eclipse
.swt
.dnd
.Transfer
;
54 import org
.eclipse
.swt
.dnd
.TransferData
;
55 import org
.eclipse
.swt
.events
.SelectionEvent
;
56 import org
.eclipse
.swt
.events
.SelectionListener
;
57 import org
.eclipse
.swt
.graphics
.Image
;
58 import org
.eclipse
.swt
.layout
.FillLayout
;
59 import org
.eclipse
.swt
.layout
.GridData
;
60 import org
.eclipse
.swt
.layout
.GridLayout
;
61 import org
.eclipse
.swt
.layout
.RowData
;
62 import org
.eclipse
.swt
.layout
.RowLayout
;
63 import org
.eclipse
.swt
.widgets
.Button
;
64 import org
.eclipse
.swt
.widgets
.Composite
;
65 import org
.eclipse
.swt
.widgets
.Label
;
66 import org
.eclipse
.swt
.widgets
.Menu
;
67 import org
.eclipse
.swt
.widgets
.MenuItem
;
68 import org
.eclipse
.swt
.widgets
.Table
;
69 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
70 import org
.eclipse
.ui
.forms
.IManagedForm
;
71 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
72 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
73 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
75 /** Definition of the process. */
76 public class ProcessBuilderPage
extends FormPage
implements SlcNames
{
77 // private final static Log log =
78 // LogFactory.getLog(ProcessBuilderPage.class);
80 public final static String ID
= "processBuilderPage";
82 /** To be displayed in empty lists */
83 final static String NONE
= "<none>";
85 private Node processNode
;
86 private Session agentSession
;
88 private TreeViewer flowsViewer
;
89 private TableViewer valuesViewer
;
90 private Label statusLabel
;
92 private Button remove
;
95 private AbstractFormPart formPart
;
96 private EventListener statusObserver
;
98 public ProcessBuilderPage(ProcessEditor editor
, Node processNode
) {
99 super(editor
, ID
, "Definition");
100 this.processNode
= processNode
;
102 this.agentSession
= processNode
.getSession().getRepository().login();
103 } catch (RepositoryException e
) {
104 throw new SlcException("Cannot open agent session", e
);
109 protected void createFormContent(IManagedForm mf
) {
111 ScrolledForm form
= mf
.getForm();
112 form
.setExpandHorizontal(true);
113 form
.setExpandVertical(true);
114 form
.setText("Process " + processNode
.getName());
115 GridLayout mainLayout
= new GridLayout(1, true);
116 form
.getBody().setLayout(mainLayout
);
118 createControls(form
.getBody());
119 createBuilder(form
.getBody());
122 formPart
= new AbstractFormPart() {
125 getManagedForm().addPart(formPart
);
128 statusObserver
= new AsyncUiEventListener(form
.getDisplay()) {
129 protected void onEventInUiThread(List
<Event
> events
) {
133 ObservationManager observationManager
= processNode
.getSession().getWorkspace().getObservationManager();
134 observationManager
.addEventListener(statusObserver
, Event
.PROPERTY_CHANGED
, processNode
.getPath(), true,
137 // make sure all controls are in line with status
143 } catch (RepositoryException e
) {
144 throw new SlcException("Cannot create form content", e
);
148 protected void createControls(Composite parent
) {
149 FormToolkit tk
= getManagedForm().getToolkit();
151 Composite controls
= tk
.createComposite(parent
);
152 controls
.setLayout(new RowLayout());
153 controls
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
155 run
= tk
.createButton(controls
, null, SWT
.PUSH
);
156 run
.setToolTipText("Run");
157 run
.setImage(SlcImages
.LAUNCH
);
158 run
.addSelectionListener(new SelectionListener() {
159 public void widgetSelected(SelectionEvent e
) {
160 if (isFinished(getProcessStatus())) {
161 ((ProcessEditor
) getEditor()).relaunch();
162 } else if (isRunning(getProcessStatus())) {
163 ((ProcessEditor
) getEditor()).kill();
165 ((ProcessEditor
) getEditor()).process();
169 public void widgetDefaultSelected(SelectionEvent e
) {
174 remove
= tk
.createButton(controls
, null, SWT
.PUSH
);
175 remove
.setImage(SlcImages
.REMOVE_ONE
);
176 remove
.setToolTipText("Remove selected flows");
177 remove
.addSelectionListener(new SelectionListener() {
178 public void widgetSelected(SelectionEvent e
) {
179 removeSelectedFlows();
182 public void widgetDefaultSelected(SelectionEvent e
) {
187 clear
= tk
.createButton(controls
, null, SWT
.PUSH
);
188 clear
.setImage(SlcImages
.REMOVE_ALL
);
189 clear
.setToolTipText("Clear all flows");
190 clear
.addSelectionListener(new SelectionListener() {
191 public void widgetSelected(SelectionEvent e
) {
195 public void widgetDefaultSelected(SelectionEvent e
) {
200 Composite statusComposite
= tk
.createComposite(controls
);
201 RowData rowData
= new RowData();
204 statusComposite
.setLayoutData(rowData
);
205 statusComposite
.setLayout(new FillLayout());
206 statusLabel
= tk
.createLabel(statusComposite
, getProcessStatus());
210 protected void createBuilder(Composite parent
) {
211 FormToolkit tk
= getManagedForm().getToolkit();
212 SashForm sashForm
= new SashForm(parent
, SWT
.HORIZONTAL
);
213 sashForm
.setSashWidth(4);
214 GridData sahFormGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
215 sahFormGd
.widthHint
= 400;
216 sashForm
.setLayoutData(sahFormGd
);
218 Composite flowsComposite
= tk
.createComposite(sashForm
);
219 flowsComposite
.setLayout(new GridLayout(1, false));
221 flowsViewer
= new TreeViewer(flowsComposite
);
222 flowsViewer
.getTree().setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
223 flowsViewer
.setLabelProvider(new FlowsLabelProvider());
224 flowsViewer
.setContentProvider(new FlowsContentProvider());
225 flowsViewer
.addSelectionChangedListener(new FlowsSelectionListener());
227 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
228 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
229 flowsViewer
.addDropSupport(operations
, tt
, new FlowsDropListener(flowsViewer
));
234 flowsViewer
.setInput(getEditorSite());
235 flowsViewer
.setInput(processNode
);
237 Composite valuesComposite
= tk
.createComposite(sashForm
);
238 valuesComposite
.setLayout(new GridLayout(1, false));
240 valuesViewer
= new TableViewer(valuesComposite
);
241 GridData valuedGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
242 // valuedGd.widthHint = 200;
243 valuesViewer
.getTable().setLayoutData(valuedGd
);
244 valuesViewer
.getTable().setHeaderVisible(true);
246 valuesViewer
.setContentProvider(new ValuesContentProvider());
247 initializeValuesViewer(valuesViewer
);
248 sashForm
.setWeights(getWeights());
249 valuesViewer
.setInput(getEditorSite());
252 /** Creates the columns of the values viewer */
253 protected void initializeValuesViewer(TableViewer viewer
) {
254 String
[] titles
= { "Name", "Value" };
255 int[] bounds
= { 200, 100 };
257 for (int i
= 0; i
< titles
.length
; i
++) {
258 TableViewerColumn column
= new TableViewerColumn(viewer
, SWT
.NONE
);
259 column
.getColumn().setText(titles
[i
]);
260 column
.getColumn().setWidth(bounds
[i
]);
261 column
.getColumn().setResizable(true);
262 column
.getColumn().setMoveable(true);
264 column
.setLabelProvider(new ColumnLabelProvider() {
265 public String
getText(Object element
) {
267 Node specAttrNode
= (Node
) element
;
268 return specAttrNode
.getName();
269 } catch (RepositoryException e
) {
270 throw new SlcException("Cannot get value", e
);
275 column
.setLabelProvider(new ColumnLabelProvider() {
276 public String
getText(Object element
) {
277 return getAttributeSpecText((Node
) element
);
280 column
.setEditingSupport(new ValuesEditingSupport(viewer
));
284 Table table
= viewer
.getTable();
285 table
.setHeaderVisible(false);
286 table
.setLinesVisible(true);
289 protected int[] getWeights() {
290 return new int[] { 50, 50 };
296 /** Reflects a status change */
297 protected void statusChanged() {
298 String status
= getProcessStatus();
299 statusLabel
.setText(status
);
300 Boolean isEditable
= isEditable(status
);
301 run
.setEnabled(status
.equals(ExecutionProcess
.RUNNING
) || isEditable
);
302 remove
.setEnabled(isEditable
);
303 clear
.setEnabled(isEditable
);
304 // flowsViewer.getTree().setEnabled(isEditable);
305 if (status
.equals(ExecutionProcess
.RUNNING
)) {
306 run
.setEnabled(true);
307 run
.setImage(SlcImages
.KILL
);
308 run
.setToolTipText("Kill");
309 } else if (isFinished(status
)) {
310 run
.setEnabled(true);
311 run
.setImage(SlcImages
.RELAUNCH
);
312 run
.setToolTipText("Relaunch");
315 if (flowsViewer
!= null)
316 flowsViewer
.refresh();
319 /** Adds initial flows from the editor input if any */
320 protected void addInitialFlows() {
321 for (String path
: ((ProcessEditorInput
) getEditorInput()).getInitialFlowPaths()) {
329 * @param path the path of the flow
331 protected void addFlow(String path
) {
333 Node flowNode
= agentSession
.getNode(path
);
334 Node realizedFlowNode
= processNode
.getNode(SLC_FLOW
).addNode(SLC_FLOW
);
335 realizedFlowNode
.setProperty(SLC_NAME
, flowNode
.getProperty(SLC_NAME
).getString());
336 realizedFlowNode
.addMixin(SlcTypes
.SLC_REALIZED_FLOW
);
337 Node address
= realizedFlowNode
.addNode(SLC_ADDRESS
, NodeType
.NT_ADDRESS
);
338 address
.setProperty(Property
.JCR_PATH
, path
);
340 // copy spec attributes
342 if (flowNode
.hasProperty(SLC_SPEC
)) {
343 Node executionSpecNode
= flowNode
.getProperty(SLC_SPEC
).getNode();
344 specAttrsBase
= executionSpecNode
;
345 String executionSpecName
= executionSpecNode
.getProperty(SLC_NAME
).getString();
346 realizedFlowNode
.setProperty(SLC_SPEC
, executionSpecName
);
348 specAttrsBase
= flowNode
;
350 specAttrs
: for (NodeIterator nit
= specAttrsBase
.getNodes(); nit
.hasNext();) {
351 Node specAttrNode
= nit
.nextNode();
352 String attrName
= specAttrNode
.getName();
353 if (!specAttrNode
.isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
355 Node realizedAttrNode
= realizedFlowNode
.addNode(specAttrNode
.getName());
356 JcrUtils
.copy(specAttrNode
, realizedAttrNode
);
358 // override with flow value
359 if (flowNode
.hasNode(attrName
)) {
360 // assuming this is a primitive
361 Node attrNode
= flowNode
.getNode(attrName
);
362 if (attrNode
.hasProperty(SLC_VALUE
))
363 realizedAttrNode
.setProperty(SLC_VALUE
, attrNode
.getProperty(SLC_VALUE
).getValue());
368 StringBuilder editorTitle
= new StringBuilder();
369 NodeIterator it
= realizedFlowNode
.getParent().getNodes(SLC_FLOW
);
370 while (it
.hasNext()) {
371 Node rFlowNode
= it
.nextNode();
372 String name
= rFlowNode
.getProperty(SLC_NAME
).getString();
373 editorTitle
.append(name
).append(' ');
375 ((ProcessEditor
) getEditor()).setEditorTitle(editorTitle
.toString());
377 flowsViewer
.refresh();
378 formPart
.markDirty();
379 } catch (RepositoryException e
) {
380 throw new SlcException("Cannot add flow " + path
, e
);
384 @SuppressWarnings("unchecked")
385 protected void removeSelectedFlows() {
386 if (!flowsViewer
.getSelection().isEmpty()) {
387 Iterator
<Object
> it
= ((StructuredSelection
) flowsViewer
.getSelection()).iterator();
388 while (it
.hasNext()) {
389 Node node
= (Node
) it
.next();
392 } catch (RepositoryException e
) {
393 throw new SlcException("Cannot remove " + node
, e
);
396 flowsViewer
.refresh();
397 formPart
.markDirty();
401 protected void removeAllFlows() {
403 for (NodeIterator nit
= processNode
.getNode(SLC_FLOW
).getNodes(); nit
.hasNext();) {
404 nit
.nextNode().remove();
406 flowsViewer
.refresh();
407 formPart
.markDirty();
408 } catch (RepositoryException e
) {
409 throw new SlcException("Cannot remove flows from " + processNode
, e
);
413 public void commit(Boolean onSave
) {
415 statusLabel
.setText(getProcessStatus());
416 formPart
.commit(onSave
);
422 protected String
getProcessStatus() {
424 return processNode
.getProperty(SLC_STATUS
).getString();
425 } catch (RepositoryException e
) {
426 throw new SlcException("Cannot retrieve status for " + processNode
, e
);
430 /** Optimization so that we don't call the node each time */
431 protected static Boolean
isEditable(String status
) {
432 return status
.equals(ExecutionProcess
.NEW
) || status
.equals(ExecutionProcess
.INITIALIZED
);
435 protected static Boolean
isFinished(String status
) {
436 return status
.equals(ExecutionProcess
.COMPLETED
) || status
.equals(ExecutionProcess
.ERROR
)
437 || status
.equals(ExecutionProcess
.KILLED
);
440 protected static Boolean
isRunning(String status
) {
441 return status
.equals(ExecutionProcess
.RUNNING
);
448 public void dispose() {
449 JcrUtils
.unregisterQuietly(processNode
, statusObserver
);
450 JcrUtils
.logoutQuietly(agentSession
);
457 protected static String
getAttributeSpecText(Node specAttrNode
) {
459 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
460 if (!specAttrNode
.hasProperty(SLC_VALUE
))
462 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
463 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
))
464 return "****************";
465 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
.getProperty(SLC_VALUE
).getString());
466 return value
.toString();
467 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
468 if (specAttrNode
.hasProperty(SLC_VALUE
)) {
469 int value
= (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
470 NodeIterator children
= specAttrNode
.getNodes();
472 while (children
.hasNext()) {
473 Node child
= children
.nextNode();
475 return child
.getProperty(Property
.JCR_TITLE
).getString();
478 throw new SlcException("No child node with index " + value
+ " for spec attribute " + specAttrNode
);
482 throw new SlcException("Unsupported type for spec attribute " + specAttrNode
);
483 } catch (RepositoryException e
) {
484 throw new SlcException("Cannot get value", e
);
491 class FlowsContentProvider
implements ITreeContentProvider
{
492 public Object
[] getElements(Object obj
) {
493 if (!(obj
instanceof Node
))
494 return new Object
[0];
497 Node node
= (Node
) obj
;
498 List
<Node
> children
= new ArrayList
<Node
>();
499 for (NodeIterator nit
= node
.getNode(SLC_FLOW
).getNodes(); nit
.hasNext();) {
500 Node flowNode
= nit
.nextNode();
501 children
.add(flowNode
);
503 return children
.toArray();
504 } catch (RepositoryException e
) {
505 throw new SlcException("Cannot list flows of " + obj
, e
);
509 public void inputChanged(Viewer arg0
, Object arg1
, Object arg2
) {
512 public void dispose() {
515 public Object
[] getChildren(Object parentElement
) {
516 // no children for the time being
520 public Object
getParent(Object element
) {
524 public boolean hasChildren(Object element
) {
530 static class FlowsLabelProvider
extends ColumnLabelProvider
{
532 public String
getText(Object element
) {
533 Node node
= (Node
) element
;
535 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
536 if (node
.hasNode(SLC_ADDRESS
)) {
537 String path
= node
.getNode(SLC_ADDRESS
).getProperty(Property
.JCR_PATH
).getString();
538 String executionModuleName
= SlcJcrUtils
.moduleName(path
);
539 // Node executionModuleNode = node.getSession().getNode(
540 // SlcJcrUtils.modulePath(path));
541 // String executionModuleName = executionModuleNode
542 // .getProperty(SLC_NAME).getString();
543 return executionModuleName
+ ":" + SlcJcrUtils
.flowRelativePath(path
);
546 } catch (RepositoryException e
) {
547 throw new SlcException("Cannot display " + element
, e
);
549 return super.getText(element
);
553 public Image
getImage(Object element
) {
554 Node node
= (Node
) element
;
556 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
557 if (node
.hasProperty(SLC_STATUS
)) {
558 String status
= node
.getProperty(SLC_STATUS
).getString();
559 // TODO: factorize with process view ?
560 if (status
.equals(ExecutionProcess
.RUNNING
))
561 return SlcImages
.PROCESS_RUNNING
;
562 else if (status
.equals(ExecutionProcess
.ERROR
) || status
.equals(ExecutionProcess
.KILLED
))
563 return SlcImages
.PROCESS_ERROR
;
564 else if (status
.equals(ExecutionProcess
.COMPLETED
))
565 return SlcImages
.PROCESS_COMPLETED
;
567 return SlcImages
.FLOW
;
569 } catch (RepositoryException e
) {
570 throw new SlcException("Cannot display " + element
, e
);
572 return super.getImage(element
);
577 /** Parameter view is updated each time a new line is selected */
578 class FlowsSelectionListener
implements ISelectionChangedListener
{
579 public void selectionChanged(SelectionChangedEvent evt
) {
580 if (evt
.getSelection().isEmpty()) {
581 valuesViewer
.setInput(getEditorSite());
584 Node realizedFlowNode
= (Node
) ((IStructuredSelection
) evt
.getSelection()).getFirstElement();
585 valuesViewer
.setInput(realizedFlowNode
);
590 * Add a context menu that call private methods. It only relies on selected
591 * item(s) not on parameter that are passed in the menuAboutToShow method
593 private void addContextMenu() {
594 Menu menu
= new Menu(flowsViewer
.getControl());
596 MenuItem removeItems
= new MenuItem(menu
, SWT
.PUSH
);
597 removeItems
.addSelectionListener(new SelectionListener() {
599 public void widgetSelected(SelectionEvent e
) {
600 removeSelectedFlows();
603 public void widgetDefaultSelected(SelectionEvent e
) {
606 removeItems
.setText("Remove selected flow(s)");
608 MenuItem removeAllItems
= new MenuItem(menu
, SWT
.PUSH
);
609 removeAllItems
.addSelectionListener(new SelectionListener() {
611 public void widgetSelected(SelectionEvent e
) {
615 public void widgetDefaultSelected(SelectionEvent e
) {
618 removeAllItems
.setText("Remove all flows");
619 flowsViewer
.getTree().setMenu(menu
);
622 /** Manages drop event. */
623 class FlowsDropListener
extends ViewerDropAdapter
{
625 public FlowsDropListener(Viewer viewer
) {
630 public boolean performDrop(Object data
) {
632 // Parse the received String, paths are separated with a carriage
634 String
[] paths
= data
.toString().split(new String("\n"));
635 SortedSet
<String
> resultPaths
= new TreeSet
<String
>();
636 for (String path
: paths
) {
638 // either a node or a whole directory can have been dragged
639 QueryManager qm
= processNode
.getSession().getWorkspace().getQueryManager();
640 String statement
= "SELECT * FROM [" + SlcTypes
.SLC_EXECUTION_FLOW
+ "] WHERE ISDESCENDANTNODE(['"
641 + path
+ "']) OR ISSAMENODE(['" + path
+ "'])";
642 Query query
= qm
.createQuery(statement
, Query
.JCR_SQL2
);
645 for (NodeIterator nit
= query
.execute().getNodes(); nit
.hasNext();) {
646 String currPath
= nit
.nextNode().getPath();
647 // do not add twice a same flow
648 if (!resultPaths
.contains(currPath
))
649 resultPaths
.add(currPath
);
651 } catch (RepositoryException e
) {
652 throw new SlcException("Cannot query flows under " + path
, e
);
655 for (String p
: resultPaths
) {
663 public boolean validateDrop(Object target
, int operation
, TransferData transferType
) {
664 return isEditable(getProcessStatus());
671 static class ValuesContentProvider
implements IStructuredContentProvider
{
673 public Object
[] getElements(Object inputElement
) {
674 if (!(inputElement
instanceof Node
))
675 return new Object
[0];
678 Node realizedFlowNode
= (Node
) inputElement
;
679 List
<Node
> specAttributes
= new ArrayList
<Node
>();
680 specAttrs
: for (NodeIterator nit
= realizedFlowNode
.getNodes(); nit
.hasNext();) {
681 Node specAttrNode
= nit
.nextNode();
682 if (!specAttrNode
.isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
684 // workaround to enable hiding of necessary but unusable
686 else if (specAttrNode
.hasProperty(SlcNames
.SLC_IS_HIDDEN
)
687 && specAttrNode
.getProperty(SlcNames
.SLC_IS_HIDDEN
).getBoolean())
689 specAttributes
.add(specAttrNode
);
691 return specAttributes
.toArray();
692 } catch (RepositoryException e
) {
693 throw new SlcException("Cannot get elements", e
);
697 public void dispose() {
700 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
704 class ValuesEditingSupport
extends EditingSupport
{
705 private final TableViewer tableViewer
;
707 public ValuesEditingSupport(ColumnViewer viewer
) {
709 tableViewer
= (TableViewer
) viewer
;
713 protected CellEditor
getCellEditor(Object element
) {
715 Node specAttrNode
= (Node
) element
;
716 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
717 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
718 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
)) {
719 return new TextCellEditor(tableViewer
.getTable(), SWT
.PASSWORD
);
721 return new TextCellEditor(tableViewer
.getTable());
723 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
724 NodeIterator children
= specAttrNode
.getNodes();
725 ArrayList
<String
> items
= new ArrayList
<String
>();
726 while (children
.hasNext()) {
727 Node child
= children
.nextNode();
728 if (child
.isNodeType(NodeType
.MIX_TITLE
))
729 items
.add(child
.getProperty(Property
.JCR_TITLE
).getString());
731 return new ComboBoxCellEditor(tableViewer
.getTable(), items
.toArray(new String
[items
.size()]));
734 } catch (RepositoryException e
) {
735 throw new SlcException("Cannot get cell editor", e
);
740 protected boolean canEdit(Object element
) {
742 Node specAttrNode
= (Node
) element
;
743 Boolean cannotEdit
= specAttrNode
.getProperty(SLC_IS_IMMUTABLE
).getBoolean()
744 || specAttrNode
.getProperty(SLC_IS_CONSTANT
).getBoolean();
745 return !cannotEdit
&& isSupportedAttributeType(specAttrNode
);
746 } catch (RepositoryException e
) {
747 throw new SlcException("Cannot check whether " + element
+ " is editable", e
);
752 * Supports {@link SlcTypes#SLC_PRIMITIVE_SPEC_ATTRIBUTE} and
753 * {@link SlcTypes#SLC_REF_SPEC_ATTRIBUTE}
755 protected boolean isSupportedAttributeType(Node specAttrNode
) throws RepositoryException
{
756 return specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)
757 || specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
);
761 protected Object
getValue(Object element
) {
762 Node specAttrNode
= (Node
) element
;
764 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
765 if (!specAttrNode
.hasProperty(SLC_VALUE
))
767 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
768 // TODO optimize based on data type?
769 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
.getProperty(SLC_VALUE
).getString());
770 return value
.toString();
771 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
772 if (!specAttrNode
.hasProperty(SLC_VALUE
))
774 // return the index of the sub node as set by setValue()
775 // in the future we may manage references as well
776 return (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
778 throw new SlcException("Unsupported type for spec attribute " + specAttrNode
);
779 } catch (RepositoryException e
) {
780 throw new SlcException("Cannot get value for " + element
, e
);
785 protected void setValue(Object element
, Object value
) {
787 Node specAttrNode
= (Node
) element
;
788 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
789 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
790 SlcJcrUtils
.setPrimitiveAsProperty(specAttrNode
, SLC_VALUE
, type
, value
);
791 valuesViewer
.refresh();
792 formPart
.markDirty();
793 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
794 specAttrNode
.setProperty(SLC_VALUE
, ((Integer
) value
).longValue());
795 valuesViewer
.refresh();
796 formPart
.markDirty();
798 } catch (RepositoryException e
) {
799 throw new SlcException("Cannot get celle editor", e
);