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
.Table
;
81 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
82 import org
.eclipse
.ui
.forms
.IManagedForm
;
83 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
84 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
85 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
87 /** Definition of the process. */
88 public class ProcessBuilderPage
extends FormPage
implements SlcNames
{
89 public final static String ID
= "processBuilderPage";
91 /** To be displayed in empty lists */
92 final static String NONE
= "<none>";
94 private Node processNode
;
96 private TreeViewer flowsViewer
;
97 private TableViewer valuesViewer
;
98 private Label statusLabel
;
100 private Button remove
;
101 private Button clear
;
103 private AbstractFormPart formPart
;
104 private EventListener statusObserver
;
106 public ProcessBuilderPage(ProcessEditor editor
, Node processNode
) {
107 super(editor
, ID
, "Definition");
108 this.processNode
= processNode
;
112 protected void createFormContent(IManagedForm mf
) {
114 ScrolledForm form
= mf
.getForm();
115 form
.setExpandHorizontal(true);
116 form
.setExpandVertical(true);
117 form
.setText("Process " + processNode
.getName());
118 GridLayout mainLayout
= new GridLayout(1, true);
119 form
.getBody().setLayout(mainLayout
);
121 createControls(form
.getBody());
122 createBuilder(form
.getBody());
125 formPart
= new AbstractFormPart() {
128 getManagedForm().addPart(formPart
);
131 statusObserver
= new AsyncUiEventListener(form
.getDisplay()) {
132 protected void onEventInUiThread(List
<Event
> events
) {
136 ObservationManager observationManager
= processNode
.getSession()
137 .getWorkspace().getObservationManager();
138 observationManager
.addEventListener(statusObserver
,
139 Event
.PROPERTY_CHANGED
, processNode
.getPath(), true, null,
142 // make sure all controls are in line with status
148 } catch (RepositoryException e
) {
149 throw new ArgeoException("Cannot create form content", e
);
153 protected void createControls(Composite parent
) {
154 FormToolkit tk
= getManagedForm().getToolkit();
156 Composite controls
= tk
.createComposite(parent
);
157 controls
.setLayout(new RowLayout());
158 controls
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
160 run
= tk
.createButton(controls
, null, SWT
.PUSH
);
161 run
.setToolTipText("Run");
162 run
.setImage(SlcImages
.LAUNCH
);
163 run
.addSelectionListener(new SelectionListener() {
164 public void widgetSelected(SelectionEvent e
) {
165 if (isFinished(getProcessStatus())) {
166 ((ProcessEditor
) getEditor()).relaunch();
167 } else if (isRunning(getProcessStatus())) {
168 ((ProcessEditor
) getEditor()).kill();
170 ((ProcessEditor
) getEditor()).process();
174 public void widgetDefaultSelected(SelectionEvent e
) {
179 remove
= tk
.createButton(controls
, null, SWT
.PUSH
);
180 remove
.setImage(SlcImages
.REMOVE_ONE
);
181 remove
.setToolTipText("Remove selected flows");
182 remove
.addSelectionListener(new SelectionListener() {
183 public void widgetSelected(SelectionEvent e
) {
184 removeSelectedFlows();
187 public void widgetDefaultSelected(SelectionEvent e
) {
192 clear
= tk
.createButton(controls
, null, SWT
.PUSH
);
193 clear
.setImage(SlcImages
.REMOVE_ALL
);
194 clear
.setToolTipText("Clear all flows");
195 clear
.addSelectionListener(new SelectionListener() {
196 public void widgetSelected(SelectionEvent e
) {
200 public void widgetDefaultSelected(SelectionEvent e
) {
205 Composite statusComposite
= tk
.createComposite(controls
);
206 RowData rowData
= new RowData();
209 statusComposite
.setLayoutData(rowData
);
210 statusComposite
.setLayout(new FillLayout());
211 statusLabel
= tk
.createLabel(statusComposite
, getProcessStatus());
215 protected void createBuilder(Composite parent
) {
216 FormToolkit tk
= getManagedForm().getToolkit();
217 SashForm sashForm
= new SashForm(parent
, SWT
.HORIZONTAL
);
218 sashForm
.setSashWidth(4);
219 GridData sahFormGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
220 sahFormGd
.widthHint
= 400;
221 sashForm
.setLayoutData(sahFormGd
);
223 Composite flowsComposite
= tk
.createComposite(sashForm
);
224 flowsComposite
.setLayout(new GridLayout(1, false));
226 flowsViewer
= new TreeViewer(flowsComposite
);
227 flowsViewer
.getTree().setLayoutData(
228 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
229 flowsViewer
.setLabelProvider(new FlowsLabelProvider());
230 flowsViewer
.setContentProvider(new FlowsContentProvider());
231 flowsViewer
.addSelectionChangedListener(new FlowsSelectionListener());
233 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
234 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
235 flowsViewer
.addDropSupport(operations
, tt
, new FlowsDropListener(
238 flowsViewer
.setInput(getEditorSite());
239 flowsViewer
.setInput(processNode
);
241 Composite valuesComposite
= tk
.createComposite(sashForm
);
242 valuesComposite
.setLayout(new GridLayout(1, false));
244 valuesViewer
= new TableViewer(valuesComposite
);
245 GridData valuedGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
246 // valuedGd.widthHint = 200;
247 valuesViewer
.getTable().setLayoutData(valuedGd
);
248 valuesViewer
.getTable().setHeaderVisible(true);
250 valuesViewer
.setContentProvider(new ValuesContentProvider());
251 initializeValuesViewer(valuesViewer
);
252 sashForm
.setWeights(getWeights());
253 valuesViewer
.setInput(getEditorSite());
256 /** Creates the columns of the values viewer */
257 protected void initializeValuesViewer(TableViewer viewer
) {
258 String
[] titles
= { "Name", "Value" };
259 int[] bounds
= { 200, 100 };
261 for (int i
= 0; i
< titles
.length
; i
++) {
262 TableViewerColumn column
= new TableViewerColumn(viewer
, SWT
.NONE
);
263 column
.getColumn().setText(titles
[i
]);
264 column
.getColumn().setWidth(bounds
[i
]);
265 column
.getColumn().setResizable(true);
266 column
.getColumn().setMoveable(true);
268 column
.setLabelProvider(new ColumnLabelProvider() {
269 public String
getText(Object element
) {
271 Node specAttrNode
= (Node
) element
;
272 return specAttrNode
.getName();
273 } catch (RepositoryException e
) {
274 throw new SlcException("Cannot get value", e
);
279 column
.setLabelProvider(new ColumnLabelProvider() {
280 public String
getText(Object element
) {
281 return getAttributeSpecText((Node
) element
);
284 column
.setEditingSupport(new ValuesEditingSupport(viewer
));
288 Table table
= viewer
.getTable();
289 table
.setHeaderVisible(false);
290 table
.setLinesVisible(true);
293 protected int[] getWeights() {
294 return new int[] { 50, 50 };
300 /** Reflects a status change */
301 protected void statusChanged() {
302 String status
= getProcessStatus();
303 statusLabel
.setText(status
);
304 Boolean isEditable
= isEditable(status
);
305 run
.setEnabled(status
.equals(ExecutionProcess
.RUNNING
) || isEditable
);
306 remove
.setEnabled(isEditable
);
307 clear
.setEnabled(isEditable
);
308 // flowsViewer.getTree().setEnabled(isEditable);
309 if (status
.equals(ExecutionProcess
.RUNNING
)) {
310 run
.setEnabled(true);
311 run
.setImage(SlcImages
.KILL
);
312 run
.setToolTipText("Kill");
313 } else if (isFinished(status
)) {
314 run
.setEnabled(true);
315 run
.setImage(SlcImages
.RELAUNCH
);
316 run
.setToolTipText("Relaunch");
319 if (flowsViewer
!= null)
320 flowsViewer
.refresh();
323 /** Adds initial flows from the editor input if any */
324 protected void addInitialFlows() {
325 for (String path
: ((ProcessEditorInput
) getEditorInput())
326 .getInitialFlowPaths()) {
335 * the path of the flow
337 protected void addFlow(String path
) {
339 Node flowNode
= processNode
.getSession().getNode(path
);
340 Node realizedFlowNode
= processNode
.getNode(SLC_FLOW
).addNode(
342 realizedFlowNode
.addMixin(SlcTypes
.SLC_REALIZED_FLOW
);
343 Node address
= realizedFlowNode
.addNode(SLC_ADDRESS
,
344 NodeType
.NT_ADDRESS
);
345 address
.setProperty(Property
.JCR_PATH
, path
);
347 // copy spec attributes
349 if (flowNode
.hasProperty(SLC_SPEC
)) {
350 Node executionSpecNode
= flowNode
.getProperty(SLC_SPEC
)
352 specAttrsBase
= executionSpecNode
;
353 String executionSpecName
= executionSpecNode
.getProperty(
354 SLC_NAME
).getString();
355 realizedFlowNode
.setProperty(SLC_SPEC
, executionSpecName
);
357 specAttrsBase
= flowNode
;
359 specAttrs
: for (NodeIterator nit
= specAttrsBase
.getNodes(); nit
361 Node specAttrNode
= nit
.nextNode();
362 String attrName
= specAttrNode
.getName();
364 .isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
366 Node realizedAttrNode
= realizedFlowNode
.addNode(specAttrNode
368 JcrUtils
.copy(specAttrNode
, realizedAttrNode
);
370 // override with flow value
371 if (flowNode
.hasNode(attrName
)) {
372 // assuming this is a primitive
373 Node attrNode
= flowNode
.getNode(attrName
);
374 if (attrNode
.hasProperty(SLC_VALUE
))
375 realizedAttrNode
.setProperty(SLC_VALUE
, attrNode
376 .getProperty(SLC_VALUE
).getValue());
380 flowsViewer
.refresh();
381 formPart
.markDirty();
382 } catch (RepositoryException e
) {
383 throw new SlcException("Cannot drop " + path
, e
);
387 @SuppressWarnings("unchecked")
388 protected void removeSelectedFlows() {
389 if (!flowsViewer
.getSelection().isEmpty()) {
390 Iterator
<Object
> it
= ((StructuredSelection
) flowsViewer
391 .getSelection()).iterator();
392 while (it
.hasNext()) {
393 Node node
= (Node
) it
.next();
396 } catch (RepositoryException e
) {
397 throw new ArgeoException("Cannot remove " + node
, e
);
400 flowsViewer
.refresh();
401 formPart
.markDirty();
405 protected void removeAllFlows() {
407 for (NodeIterator nit
= processNode
.getNode(SLC_FLOW
).getNodes(); nit
409 nit
.nextNode().remove();
411 flowsViewer
.refresh();
412 formPart
.markDirty();
413 } catch (RepositoryException e
) {
414 throw new ArgeoException("Cannot remove flows from " + processNode
,
419 public void commit(Boolean onSave
) {
421 statusLabel
.setText(getProcessStatus());
422 formPart
.commit(onSave
);
428 protected String
getProcessStatus() {
430 return processNode
.getProperty(SLC_STATUS
).getString();
431 } catch (RepositoryException e
) {
432 throw new SlcException("Cannot retrieve status for " + processNode
,
437 /** Optimization so that we don't call the node each time */
438 protected static Boolean
isEditable(String status
) {
439 return status
.equals(ExecutionProcess
.NEW
)
440 || status
.equals(ExecutionProcess
.INITIALIZED
);
443 protected static Boolean
isFinished(String status
) {
444 return status
.equals(ExecutionProcess
.COMPLETED
)
445 || status
.equals(ExecutionProcess
.ERROR
)
446 || status
.equals(ExecutionProcess
.KILLED
);
449 protected static Boolean
isRunning(String status
) {
450 return status
.equals(ExecutionProcess
.RUNNING
);
457 public void dispose() {
458 JcrUtils
.unregisterQuietly(processNode
, statusObserver
);
465 protected static String
getAttributeSpecText(Node specAttrNode
) {
467 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
468 if (!specAttrNode
.hasProperty(SLC_VALUE
))
470 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
471 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
))
472 return "****************";
473 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
474 .getProperty(SLC_VALUE
).getString());
475 return value
.toString();
476 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
477 if (specAttrNode
.hasProperty(SLC_VALUE
)) {
478 int value
= (int) specAttrNode
.getProperty(SLC_VALUE
)
480 NodeIterator children
= specAttrNode
.getNodes();
482 while (children
.hasNext()) {
483 Node child
= children
.nextNode();
485 return child
.getProperty(Property
.JCR_TITLE
)
489 throw new SlcException("No child node with index " + value
490 + " for spec attribute " + specAttrNode
);
494 throw new SlcException("Unsupported type for spec attribute "
496 } catch (RepositoryException e
) {
497 throw new SlcException("Cannot get value", e
);
504 class FlowsContentProvider
implements ITreeContentProvider
{
505 public Object
[] getElements(Object obj
) {
506 if (!(obj
instanceof Node
))
507 return new Object
[0];
510 Node node
= (Node
) obj
;
511 List
<Node
> children
= new ArrayList
<Node
>();
512 for (NodeIterator nit
= node
.getNode(SLC_FLOW
).getNodes(); nit
514 Node flowNode
= nit
.nextNode();
515 children
.add(flowNode
);
517 return children
.toArray();
518 } catch (RepositoryException e
) {
519 throw new SlcException("Cannot list flows of " + obj
, e
);
523 public void inputChanged(Viewer arg0
, Object arg1
, Object arg2
) {
526 public void dispose() {
529 public Object
[] getChildren(Object parentElement
) {
530 // no children for the time being
534 public Object
getParent(Object element
) {
538 public boolean hasChildren(Object element
) {
544 static class FlowsLabelProvider
extends ColumnLabelProvider
{
546 public String
getText(Object element
) {
547 Node node
= (Node
) element
;
549 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
550 if (node
.hasNode(SLC_ADDRESS
)) {
551 String path
= node
.getNode(SLC_ADDRESS
)
552 .getProperty(Property
.JCR_PATH
).getString();
553 String executionModuleName
= SlcJcrUtils
555 // Node executionModuleNode = node.getSession().getNode(
556 // SlcJcrUtils.modulePath(path));
557 // String executionModuleName = executionModuleNode
558 // .getProperty(SLC_NAME).getString();
559 return executionModuleName
+ ":"
560 + SlcJcrUtils
.flowRelativePath(path
);
563 } catch (RepositoryException e
) {
564 throw new SlcException("Cannot display " + element
, e
);
566 return super.getText(element
);
570 public Image
getImage(Object element
) {
571 Node node
= (Node
) element
;
573 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
574 if (node
.hasProperty(SLC_STATUS
)) {
575 String status
= node
.getProperty(SLC_STATUS
)
577 // TODO: factorize with process view ?
578 if (status
.equals(ExecutionProcess
.RUNNING
))
579 return SlcImages
.PROCESS_RUNNING
;
580 else if (status
.equals(ExecutionProcess
.ERROR
)
581 || status
.equals(ExecutionProcess
.KILLED
))
582 return SlcImages
.PROCESS_ERROR
;
583 else if (status
.equals(ExecutionProcess
.COMPLETED
))
584 return SlcImages
.PROCESS_COMPLETED
;
586 return SlcImages
.FLOW
;
588 } catch (RepositoryException e
) {
589 throw new SlcException("Cannot display " + element
, e
);
591 return super.getImage(element
);
596 /** Parameter view is updated each time a new line is selected */
597 class FlowsSelectionListener
implements ISelectionChangedListener
{
598 public void selectionChanged(SelectionChangedEvent evt
) {
599 if (evt
.getSelection().isEmpty()) {
600 valuesViewer
.setInput(getEditorSite());
603 Node realizedFlowNode
= (Node
) ((IStructuredSelection
) evt
604 .getSelection()).getFirstElement();
605 valuesViewer
.setInput(realizedFlowNode
);
609 /** Manages drop event. */
610 class FlowsDropListener
extends ViewerDropAdapter
{
612 public FlowsDropListener(Viewer viewer
) {
617 public boolean performDrop(Object data
) {
618 String path
= data
.toString();
620 // either a node or a whole directory was dragged
621 QueryManager qm
= processNode
.getSession().getWorkspace()
623 String statement
= "SELECT * FROM ["
624 + SlcTypes
.SLC_EXECUTION_FLOW
625 + "] WHERE ISDESCENDANTNODE(['" + path
626 + "']) OR ISSAMENODE(['" + path
+ "'])";
627 // log.debug(statement);
628 Query query
= qm
.createQuery(statement
, Query
.JCR_SQL2
);
631 SortedSet
<String
> paths
= new TreeSet
<String
>();
632 for (NodeIterator nit
= query
.execute().getNodes(); nit
634 paths
.add(nit
.nextNode().getPath());
637 for (String p
: paths
) {
641 } catch (RepositoryException e
) {
642 throw new SlcException("Cannot query flows under " + path
, e
);
647 public boolean validateDrop(Object target
, int operation
,
648 TransferData transferType
) {
649 return isEditable(getProcessStatus());
656 static class ValuesContentProvider
implements IStructuredContentProvider
{
658 public Object
[] getElements(Object inputElement
) {
659 if (!(inputElement
instanceof Node
))
660 return new Object
[0];
663 Node realizedFlowNode
= (Node
) inputElement
;
664 List
<Node
> specAttributes
= new ArrayList
<Node
>();
665 specAttrs
: for (NodeIterator nit
= realizedFlowNode
.getNodes(); nit
667 Node specAttrNode
= nit
.nextNode();
669 .isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
671 specAttributes
.add(specAttrNode
);
673 return specAttributes
.toArray();
674 } catch (RepositoryException e
) {
675 throw new SlcException("Cannot get elements", e
);
679 public void dispose() {
682 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
686 class ValuesEditingSupport
extends EditingSupport
{
687 private final TableViewer tableViewer
;
689 public ValuesEditingSupport(ColumnViewer viewer
) {
691 tableViewer
= (TableViewer
) viewer
;
695 protected CellEditor
getCellEditor(Object element
) {
697 Node specAttrNode
= (Node
) element
;
699 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
700 String type
= specAttrNode
.getProperty(SLC_TYPE
)
702 if (PrimitiveAccessor
.TYPE_PASSWORD
.equals(type
)) {
703 return new TextCellEditor(tableViewer
.getTable(),
706 return new TextCellEditor(tableViewer
.getTable());
708 } else if (specAttrNode
709 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
710 NodeIterator children
= specAttrNode
.getNodes();
711 ArrayList
<String
> items
= new ArrayList
<String
>();
712 while (children
.hasNext()) {
713 Node child
= children
.nextNode();
714 if (child
.isNodeType(NodeType
.MIX_TITLE
))
715 items
.add(child
.getProperty(Property
.JCR_TITLE
)
718 return new ComboBoxCellEditor(tableViewer
.getTable(),
719 items
.toArray(new String
[items
.size()]));
722 } catch (RepositoryException e
) {
723 throw new SlcException("Cannot get cell editor", e
);
728 protected boolean canEdit(Object element
) {
730 Node specAttrNode
= (Node
) element
;
731 Boolean cannotEdit
= specAttrNode
.getProperty(SLC_IS_IMMUTABLE
)
733 || specAttrNode
.getProperty(SLC_IS_CONSTANT
)
735 return !cannotEdit
&& isSupportedAttributeType(specAttrNode
);
736 } catch (RepositoryException e
) {
737 throw new SlcException("Cannot check whether " + element
738 + " is editable", e
);
743 * Supports {@link SlcTypes#SLC_PRIMITIVE_SPEC_ATTRIBUTE} and
744 * {@link SlcTypes#SLC_REF_SPEC_ATTRIBUTE}
746 protected boolean isSupportedAttributeType(Node specAttrNode
)
747 throws RepositoryException
{
749 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)
750 || specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
);
754 protected Object
getValue(Object element
) {
755 Node specAttrNode
= (Node
) element
;
758 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
759 if (!specAttrNode
.hasProperty(SLC_VALUE
))
761 String type
= specAttrNode
.getProperty(SLC_TYPE
)
763 // TODO optimize based on data type?
764 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
765 .getProperty(SLC_VALUE
).getString());
766 return value
.toString();
767 } else if (specAttrNode
768 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
769 if (!specAttrNode
.hasProperty(SLC_VALUE
))
771 // return the index of the sub node as set by setValue()
772 // in the future we may manage references as well
773 return (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
775 throw new SlcException("Unsupported type for spec attribute "
777 } catch (RepositoryException e
) {
778 throw new SlcException("Cannot get value for " + element
, e
);
783 protected void setValue(Object element
, Object value
) {
785 Node specAttrNode
= (Node
) element
;
787 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
788 String type
= specAttrNode
.getProperty(SLC_TYPE
)
790 SlcJcrUtils
.setPrimitiveAsProperty(specAttrNode
, SLC_VALUE
,
792 valuesViewer
.refresh();
793 formPart
.markDirty();
794 } else if (specAttrNode
795 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
796 specAttrNode
.setProperty(SLC_VALUE
,
797 ((Integer
) value
).longValue());
798 valuesViewer
.refresh();
799 formPart
.markDirty();
801 } catch (RepositoryException e
) {
802 throw new SlcException("Cannot get celle editor", e
);