2 * Copyright (C) 2007-2012 Mathieu Baudier
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
.PrimitiveUtils
;
41 import org
.argeo
.slc
.execution
.ExecutionProcess
;
42 import org
.argeo
.slc
.jcr
.SlcJcrUtils
;
43 import org
.argeo
.slc
.jcr
.SlcNames
;
44 import org
.argeo
.slc
.jcr
.SlcTypes
;
45 import org
.eclipse
.jface
.viewers
.CellEditor
;
46 import org
.eclipse
.jface
.viewers
.ColumnLabelProvider
;
47 import org
.eclipse
.jface
.viewers
.ColumnViewer
;
48 import org
.eclipse
.jface
.viewers
.ComboBoxCellEditor
;
49 import org
.eclipse
.jface
.viewers
.EditingSupport
;
50 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
51 import org
.eclipse
.jface
.viewers
.IStructuredContentProvider
;
52 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
53 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
54 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
55 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
56 import org
.eclipse
.jface
.viewers
.TableViewer
;
57 import org
.eclipse
.jface
.viewers
.TableViewerColumn
;
58 import org
.eclipse
.jface
.viewers
.TextCellEditor
;
59 import org
.eclipse
.jface
.viewers
.TreeViewer
;
60 import org
.eclipse
.jface
.viewers
.Viewer
;
61 import org
.eclipse
.jface
.viewers
.ViewerDropAdapter
;
62 import org
.eclipse
.swt
.SWT
;
63 import org
.eclipse
.swt
.custom
.SashForm
;
64 import org
.eclipse
.swt
.dnd
.DND
;
65 import org
.eclipse
.swt
.dnd
.TextTransfer
;
66 import org
.eclipse
.swt
.dnd
.Transfer
;
67 import org
.eclipse
.swt
.dnd
.TransferData
;
68 import org
.eclipse
.swt
.events
.SelectionEvent
;
69 import org
.eclipse
.swt
.events
.SelectionListener
;
70 import org
.eclipse
.swt
.graphics
.Image
;
71 import org
.eclipse
.swt
.layout
.FillLayout
;
72 import org
.eclipse
.swt
.layout
.GridData
;
73 import org
.eclipse
.swt
.layout
.GridLayout
;
74 import org
.eclipse
.swt
.layout
.RowData
;
75 import org
.eclipse
.swt
.layout
.RowLayout
;
76 import org
.eclipse
.swt
.widgets
.Button
;
77 import org
.eclipse
.swt
.widgets
.Composite
;
78 import org
.eclipse
.swt
.widgets
.Label
;
79 import org
.eclipse
.swt
.widgets
.Table
;
80 import org
.eclipse
.ui
.forms
.AbstractFormPart
;
81 import org
.eclipse
.ui
.forms
.IManagedForm
;
82 import org
.eclipse
.ui
.forms
.editor
.FormPage
;
83 import org
.eclipse
.ui
.forms
.widgets
.FormToolkit
;
84 import org
.eclipse
.ui
.forms
.widgets
.ScrolledForm
;
86 /** Definition of the process. */
87 public class ProcessBuilderPage
extends FormPage
implements SlcNames
{
88 public final static String ID
= "processBuilderPage";
89 // private final static Log log =
90 // LogFactory.getLog(ProcessBuilderPage.class);
92 /** To be displayed in empty lists */
93 final static String NONE
= "<none>";
95 private Node processNode
;
97 private TreeViewer flowsViewer
;
98 private TableViewer valuesViewer
;
99 private Label statusLabel
;
101 private Button remove
;
102 private Button clear
;
104 private AbstractFormPart formPart
;
105 private EventListener statusObserver
;
107 public ProcessBuilderPage(ProcessEditor editor
, Node processNode
) {
108 super(editor
, ID
, "Definition");
109 this.processNode
= processNode
;
113 protected void createFormContent(IManagedForm mf
) {
115 ScrolledForm form
= mf
.getForm();
116 form
.setExpandHorizontal(true);
117 form
.setExpandVertical(true);
118 form
.setText("Process " + processNode
.getName());
119 GridLayout mainLayout
= new GridLayout(1, true);
120 form
.getBody().setLayout(mainLayout
);
122 createControls(form
.getBody());
123 createBuilder(form
.getBody());
126 formPart
= new AbstractFormPart() {
129 getManagedForm().addPart(formPart
);
132 statusObserver
= new AsyncUiEventListener(form
.getDisplay()) {
133 protected void onEventInUiThread(List
<Event
> events
) {
137 ObservationManager observationManager
= processNode
.getSession()
138 .getWorkspace().getObservationManager();
139 observationManager
.addEventListener(statusObserver
,
140 Event
.PROPERTY_CHANGED
, processNode
.getPath(), true, null,
143 // make sure all controls are in line with status
149 } catch (RepositoryException e
) {
150 throw new ArgeoException("Cannot create form content", e
);
154 protected void createControls(Composite parent
) {
155 FormToolkit tk
= getManagedForm().getToolkit();
157 Composite controls
= tk
.createComposite(parent
);
158 controls
.setLayout(new RowLayout());
159 controls
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, false));
161 run
= tk
.createButton(controls
, null, SWT
.PUSH
);
162 run
.setToolTipText("Run");
163 run
.setImage(SlcImages
.LAUNCH
);
164 run
.addSelectionListener(new SelectionListener() {
165 public void widgetSelected(SelectionEvent e
) {
166 if (isFinished(getProcessStatus())) {
167 ((ProcessEditor
) getEditor()).relaunch();
168 } else if (isRunning(getProcessStatus())) {
169 ((ProcessEditor
) getEditor()).kill();
171 ((ProcessEditor
) getEditor()).process();
175 public void widgetDefaultSelected(SelectionEvent e
) {
180 remove
= tk
.createButton(controls
, null, SWT
.PUSH
);
181 remove
.setImage(SlcImages
.REMOVE_ONE
);
182 remove
.setToolTipText("Remove selected flows");
183 remove
.addSelectionListener(new SelectionListener() {
184 public void widgetSelected(SelectionEvent e
) {
185 removeSelectedFlows();
188 public void widgetDefaultSelected(SelectionEvent e
) {
193 clear
= tk
.createButton(controls
, null, SWT
.PUSH
);
194 clear
.setImage(SlcImages
.REMOVE_ALL
);
195 clear
.setToolTipText("Clear all flows");
196 clear
.addSelectionListener(new SelectionListener() {
197 public void widgetSelected(SelectionEvent e
) {
201 public void widgetDefaultSelected(SelectionEvent e
) {
206 Composite statusComposite
= tk
.createComposite(controls
);
207 RowData rowData
= new RowData();
210 statusComposite
.setLayoutData(rowData
);
211 statusComposite
.setLayout(new FillLayout());
212 statusLabel
= tk
.createLabel(statusComposite
, getProcessStatus());
216 protected void createBuilder(Composite parent
) {
217 FormToolkit tk
= getManagedForm().getToolkit();
218 SashForm sashForm
= new SashForm(parent
, SWT
.HORIZONTAL
);
219 sashForm
.setSashWidth(4);
220 GridData sahFormGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
221 sahFormGd
.widthHint
= 400;
222 sashForm
.setLayoutData(sahFormGd
);
224 Composite flowsComposite
= tk
.createComposite(sashForm
);
225 flowsComposite
.setLayout(new GridLayout(1, false));
227 flowsViewer
= new TreeViewer(flowsComposite
);
228 flowsViewer
.getTree().setLayoutData(
229 new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
230 flowsViewer
.setLabelProvider(new FlowsLabelProvider());
231 flowsViewer
.setContentProvider(new FlowsContentProvider());
232 flowsViewer
.addSelectionChangedListener(new FlowsSelectionListener());
234 int operations
= DND
.DROP_COPY
| DND
.DROP_MOVE
;
235 Transfer
[] tt
= new Transfer
[] { TextTransfer
.getInstance() };
236 flowsViewer
.addDropSupport(operations
, tt
, new FlowsDropListener(
239 flowsViewer
.setInput(getEditorSite());
240 flowsViewer
.setInput(processNode
);
242 Composite valuesComposite
= tk
.createComposite(sashForm
);
243 valuesComposite
.setLayout(new GridLayout(1, false));
245 valuesViewer
= new TableViewer(valuesComposite
);
246 GridData valuedGd
= new GridData(SWT
.FILL
, SWT
.FILL
, true, true);
247 // valuedGd.widthHint = 200;
248 valuesViewer
.getTable().setLayoutData(valuedGd
);
249 valuesViewer
.setContentProvider(new ValuesContentProvider());
250 initializeValuesViewer(valuesViewer
);
251 sashForm
.setWeights(getWeights());
252 valuesViewer
.setInput(getEditorSite());
255 /** Creates the columns of the values viewer */
256 protected void initializeValuesViewer(TableViewer viewer
) {
257 String
[] titles
= { "Name", "Value" };
258 int[] bounds
= { 200, 100 };
260 for (int i
= 0; i
< titles
.length
; i
++) {
261 TableViewerColumn column
= new TableViewerColumn(viewer
, SWT
.NONE
);
262 column
.getColumn().setText(titles
[i
]);
263 column
.getColumn().setWidth(bounds
[i
]);
264 column
.getColumn().setResizable(true);
265 column
.getColumn().setMoveable(true);
267 column
.setLabelProvider(new ColumnLabelProvider() {
268 public String
getText(Object element
) {
270 Node specAttrNode
= (Node
) element
;
271 return specAttrNode
.getName();
272 } catch (RepositoryException e
) {
273 throw new SlcException("Cannot get value", e
);
278 column
.setLabelProvider(new ColumnLabelProvider() {
279 public String
getText(Object element
) {
280 return getAttributeSpecText((Node
) element
);
283 column
.setEditingSupport(new ValuesEditingSupport(viewer
));
287 Table table
= viewer
.getTable();
288 table
.setHeaderVisible(false);
289 table
.setLinesVisible(true);
292 protected int[] getWeights() {
293 return new int[] { 50, 50 };
299 /** Reflects a status change */
300 protected void statusChanged() {
301 String status
= getProcessStatus();
302 statusLabel
.setText(status
);
303 Boolean isEditable
= isEditable(status
);
304 run
.setEnabled(status
.equals(ExecutionProcess
.RUNNING
) || isEditable
);
305 remove
.setEnabled(isEditable
);
306 clear
.setEnabled(isEditable
);
307 // flowsViewer.getTree().setEnabled(isEditable);
308 if (status
.equals(ExecutionProcess
.RUNNING
)) {
309 run
.setEnabled(true);
310 run
.setImage(SlcImages
.KILL
);
311 run
.setToolTipText("Kill");
312 } else if (isFinished(status
)) {
313 run
.setEnabled(true);
314 run
.setImage(SlcImages
.RELAUNCH
);
315 run
.setToolTipText("Relaunch");
318 if (flowsViewer
!= null)
319 flowsViewer
.refresh();
322 /** Adds initial flows from the editor input if any */
323 protected void addInitialFlows() {
324 for (String path
: ((ProcessEditorInput
) getEditorInput())
325 .getInitialFlowPaths()) {
334 * the path of the flow
336 protected void addFlow(String path
) {
338 Node flowNode
= processNode
.getSession().getNode(path
);
339 Node realizedFlowNode
= processNode
.getNode(SLC_FLOW
).addNode(
341 realizedFlowNode
.addMixin(SlcTypes
.SLC_REALIZED_FLOW
);
342 Node address
= realizedFlowNode
.addNode(SLC_ADDRESS
,
343 NodeType
.NT_ADDRESS
);
344 address
.setProperty(Property
.JCR_PATH
, path
);
346 // copy spec attributes
348 if (flowNode
.hasProperty(SLC_SPEC
)) {
349 Node executionSpecNode
= flowNode
.getProperty(SLC_SPEC
)
351 specAttrsBase
= executionSpecNode
;
352 String executionSpecName
= executionSpecNode
.getProperty(
353 SLC_NAME
).getString();
354 realizedFlowNode
.setProperty(SLC_SPEC
, executionSpecName
);
356 specAttrsBase
= flowNode
;
358 specAttrs
: for (NodeIterator nit
= specAttrsBase
.getNodes(); nit
360 Node specAttrNode
= nit
.nextNode();
361 String attrName
= specAttrNode
.getName();
363 .isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
365 Node realizedAttrNode
= realizedFlowNode
.addNode(specAttrNode
367 JcrUtils
.copy(specAttrNode
, realizedAttrNode
);
369 // override with flow value
370 if (flowNode
.hasNode(attrName
)) {
371 // assuming this is a primitive
372 realizedAttrNode
.setProperty(SLC_VALUE
,
373 flowNode
.getNode(attrName
).getProperty(SLC_VALUE
)
378 flowsViewer
.refresh();
379 formPart
.markDirty();
380 } catch (RepositoryException e
) {
381 throw new SlcException("Cannot drop " + path
, e
);
385 @SuppressWarnings("unchecked")
386 protected void removeSelectedFlows() {
387 if (!flowsViewer
.getSelection().isEmpty()) {
388 Iterator
<Object
> it
= ((StructuredSelection
) flowsViewer
389 .getSelection()).iterator();
390 while (it
.hasNext()) {
391 Node node
= (Node
) it
.next();
394 } catch (RepositoryException e
) {
395 throw new ArgeoException("Cannot remove " + node
, e
);
398 flowsViewer
.refresh();
399 formPart
.markDirty();
403 protected void removeAllFlows() {
405 for (NodeIterator nit
= processNode
.getNode(SLC_FLOW
).getNodes(); nit
407 nit
.nextNode().remove();
409 flowsViewer
.refresh();
410 formPart
.markDirty();
411 } catch (RepositoryException e
) {
412 throw new ArgeoException("Cannot remove flows from " + processNode
,
417 public void commit(Boolean onSave
) {
419 statusLabel
.setText(getProcessStatus());
420 formPart
.commit(onSave
);
426 protected String
getProcessStatus() {
428 return processNode
.getProperty(SLC_STATUS
).getString();
429 } catch (RepositoryException e
) {
430 throw new SlcException("Cannot retrieve status for " + processNode
,
435 /** Optimization so that we don't call the node each time */
436 protected static Boolean
isEditable(String status
) {
437 return status
.equals(ExecutionProcess
.NEW
)
438 || status
.equals(ExecutionProcess
.INITIALIZED
);
441 protected static Boolean
isFinished(String status
) {
442 return status
.equals(ExecutionProcess
.COMPLETED
)
443 || status
.equals(ExecutionProcess
.ERROR
)
444 || status
.equals(ExecutionProcess
.KILLED
);
447 protected static Boolean
isRunning(String status
) {
448 return status
.equals(ExecutionProcess
.RUNNING
);
455 public void dispose() {
456 JcrUtils
.unregisterQuietly(processNode
, statusObserver
);
463 // protected static Object getAttributeSpecValue(Node specAttrNode) {
465 // if (specAttrNode.isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
466 // if (!specAttrNode.hasProperty(SLC_VALUE))
468 // String type = specAttrNode.getProperty(SLC_TYPE).getString();
469 // // TODO optimize based on data type?
470 // Object value = PrimitiveUtils.convert(type, specAttrNode
471 // .getProperty(SLC_VALUE).getString());
472 // // log.debug(specAttrNode + ", type=" + type + ", value=" +
475 // } else if (specAttrNode.isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
476 // if (specAttrNode.hasNode(SLC_VALUE)) {
477 // // return the index of the sub node
478 // // in the future we may manage reference as well
479 // return specAttrNode.getProperty(SLC_VALUE).getLong();
484 // } catch (RepositoryException e) {
485 // throw new SlcException("Cannot get value", e);
490 protected static String
getAttributeSpecText(Node specAttrNode
) {
492 if (specAttrNode
.isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
493 if (!specAttrNode
.hasProperty(SLC_VALUE
))
495 String type
= specAttrNode
.getProperty(SLC_TYPE
).getString();
496 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
497 .getProperty(SLC_VALUE
).getString());
498 return value
.toString();
499 } else if (specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
500 if (specAttrNode
.hasProperty(SLC_VALUE
)) {
501 int value
= (int) specAttrNode
.getProperty(SLC_VALUE
)
503 NodeIterator children
= specAttrNode
.getNodes();
505 while (children
.hasNext()) {
506 Node child
= children
.nextNode();
508 return child
.getProperty(Property
.JCR_TITLE
)
512 throw new SlcException("No child node with index " + value
513 + " for spec attribute " + specAttrNode
);
517 throw new SlcException("Unsupported type for spec attribute "
519 } catch (RepositoryException e
) {
520 throw new SlcException("Cannot get value", e
);
527 static class FlowsContentProvider
implements ITreeContentProvider
{
528 public Object
[] getElements(Object obj
) {
529 if (!(obj
instanceof Node
))
530 return new Object
[0];
533 Node node
= (Node
) obj
;
534 List
<Node
> children
= new ArrayList
<Node
>();
535 for (NodeIterator nit
= node
.getNode(SLC_FLOW
).getNodes(); nit
537 children
.add(nit
.nextNode());
538 return children
.toArray();
539 } catch (RepositoryException e
) {
540 throw new SlcException("Cannot list children 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
{
568 public String
getText(Object element
) {
569 Node node
= (Node
) element
;
571 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
572 if (node
.hasNode(SLC_ADDRESS
)) {
573 String path
= node
.getNode(SLC_ADDRESS
)
574 .getProperty(Property
.JCR_PATH
).getString();
575 Node executionModuleNode
= node
.getSession().getNode(
576 SlcJcrUtils
.modulePath(path
));
577 String executionModuleName
= executionModuleNode
578 .getProperty(SLC_NAME
).getString();
579 return executionModuleName
+ ":"
580 + SlcJcrUtils
.flowRelativePath(path
);
583 } catch (RepositoryException e
) {
584 throw new SlcException("Cannot display " + element
, e
);
586 return super.getText(element
);
590 public Image
getImage(Object element
) {
591 Node node
= (Node
) element
;
593 if (node
.isNodeType(SlcTypes
.SLC_REALIZED_FLOW
)) {
594 if (node
.hasProperty(SLC_STATUS
)) {
595 String status
= node
.getProperty(SLC_STATUS
)
597 // TODO: factorize with process view ?
598 if (status
.equals(ExecutionProcess
.RUNNING
))
599 return SlcImages
.PROCESS_RUNNING
;
600 else if (status
.equals(ExecutionProcess
.ERROR
)
601 || status
.equals(ExecutionProcess
.KILLED
))
602 return SlcImages
.PROCESS_ERROR
;
603 else if (status
.equals(ExecutionProcess
.COMPLETED
))
604 return SlcImages
.PROCESS_COMPLETED
;
606 return SlcImages
.FLOW
;
608 } catch (RepositoryException e
) {
609 throw new SlcException("Cannot display " + element
, e
);
611 return super.getImage(element
);
616 /** Parameter view is updated each time a new line is selected */
617 class FlowsSelectionListener
implements ISelectionChangedListener
{
618 public void selectionChanged(SelectionChangedEvent evt
) {
619 if (evt
.getSelection().isEmpty()) {
620 valuesViewer
.setInput(getEditorSite());
623 Node realizedFlowNode
= (Node
) ((IStructuredSelection
) evt
624 .getSelection()).getFirstElement();
625 valuesViewer
.setInput(realizedFlowNode
);
629 /** Manages drop event. */
630 class FlowsDropListener
extends ViewerDropAdapter
{
632 public FlowsDropListener(Viewer viewer
) {
637 public boolean performDrop(Object data
) {
638 String path
= data
.toString();
640 // either a node or a whole directory was dragged
641 QueryManager qm
= processNode
.getSession().getWorkspace()
643 String statement
= "SELECT * FROM ["
644 + SlcTypes
.SLC_EXECUTION_FLOW
645 + "] WHERE ISDESCENDANTNODE(['" + path
646 + "']) OR ISSAMENODE(['" + path
+ "'])";
647 // log.debug(statement);
648 Query query
= qm
.createQuery(statement
, Query
.JCR_SQL2
);
651 SortedSet
<String
> paths
= new TreeSet
<String
>();
652 for (NodeIterator nit
= query
.execute().getNodes(); nit
654 paths
.add(nit
.nextNode().getPath());
657 for (String p
: paths
) {
661 } catch (RepositoryException e
) {
662 throw new SlcException("Cannot query flows under " + path
, e
);
667 public boolean validateDrop(Object target
, int operation
,
668 TransferData transferType
) {
669 return isEditable(getProcessStatus());
676 static class ValuesContentProvider
implements IStructuredContentProvider
{
678 public Object
[] getElements(Object inputElement
) {
679 if (!(inputElement
instanceof Node
))
680 return new Object
[0];
683 Node realizedFlowNode
= (Node
) inputElement
;
684 List
<Node
> specAttributes
= new ArrayList
<Node
>();
685 specAttrs
: for (NodeIterator nit
= realizedFlowNode
.getNodes(); nit
687 Node specAttrNode
= nit
.nextNode();
689 .isNodeType(SlcTypes
.SLC_EXECUTION_SPEC_ATTRIBUTE
))
691 specAttributes
.add(specAttrNode
);
693 return specAttributes
.toArray();
694 } catch (RepositoryException e
) {
695 throw new SlcException("Cannot get elements", e
);
699 public void dispose() {
702 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
706 class ValuesEditingSupport
extends EditingSupport
{
707 private final TableViewer tableViewer
;
709 public ValuesEditingSupport(ColumnViewer viewer
) {
711 tableViewer
= (TableViewer
) viewer
;
715 protected CellEditor
getCellEditor(Object element
) {
717 Node specAttrNode
= (Node
) element
;
719 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
720 return new TextCellEditor(tableViewer
.getTable());
721 } else if (specAttrNode
722 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
723 NodeIterator children
= specAttrNode
.getNodes();
724 ArrayList
<String
> items
= new ArrayList
<String
>();
725 while (children
.hasNext()) {
726 Node child
= children
.nextNode();
727 if (child
.isNodeType(NodeType
.MIX_TITLE
))
728 items
.add(child
.getProperty(Property
.JCR_TITLE
)
731 return new ComboBoxCellEditor(tableViewer
.getTable(),
732 items
.toArray(new String
[items
.size()]));
735 } catch (RepositoryException e
) {
736 throw new SlcException("Cannot get celle editor", e
);
741 protected boolean canEdit(Object element
) {
743 Node specAttrNode
= (Node
) element
;
744 return !(specAttrNode
.getProperty(SLC_IS_IMMUTABLE
)
745 .getBoolean() || specAttrNode
.getProperty(
746 SLC_IS_CONSTANT
).getBoolean())
747 && isSupportedAttributeType(specAttrNode
);
748 } catch (RepositoryException e
) {
749 throw new SlcException("Cannot check whether " + element
750 + " is editable", e
);
755 * Supports {@link SlcTypes#SLC_PRIMITIVE_SPEC_ATTRIBUTE} and
756 * {@link SlcTypes#SLC_REF_SPEC_ATTRIBUTE}
758 protected boolean isSupportedAttributeType(Node specAttrNode
)
759 throws RepositoryException
{
761 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)
762 || specAttrNode
.isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
);
766 protected Object
getValue(Object element
) {
767 Node specAttrNode
= (Node
) element
;
769 // Object value = getAttributeSpecValue(specAttrNode);
770 // if (value == null)
771 // throw new SlcException("Unsupported attribute " + element);
773 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
774 if (!specAttrNode
.hasProperty(SLC_VALUE
))
776 String type
= specAttrNode
.getProperty(SLC_TYPE
)
778 // TODO optimize based on data type?
779 Object value
= PrimitiveUtils
.convert(type
, specAttrNode
780 .getProperty(SLC_VALUE
).getString());
781 return value
.toString();
782 } else if (specAttrNode
783 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
784 if (!specAttrNode
.hasProperty(SLC_VALUE
))
786 // return the index of the sub node as set by setValue()
787 // in the future we may manage references as well
788 return (int) specAttrNode
.getProperty(SLC_VALUE
).getLong();
790 throw new SlcException("Unsupported type for spec attribute "
792 } catch (RepositoryException e
) {
793 throw new SlcException("Cannot get value for " + element
, e
);
798 protected void setValue(Object element
, Object value
) {
800 Node specAttrNode
= (Node
) element
;
802 .isNodeType(SlcTypes
.SLC_PRIMITIVE_SPEC_ATTRIBUTE
)) {
803 String type
= specAttrNode
.getProperty(SLC_TYPE
)
805 SlcJcrUtils
.setPrimitiveAsProperty(specAttrNode
, SLC_VALUE
,
807 valuesViewer
.refresh();
808 formPart
.markDirty();
809 } else if (specAttrNode
810 .isNodeType(SlcTypes
.SLC_REF_SPEC_ATTRIBUTE
)) {
811 specAttrNode
.setProperty(SLC_VALUE
,
812 ((Integer
) value
).longValue());
813 valuesViewer
.refresh();
814 formPart
.markDirty();
816 } catch (RepositoryException e
) {
817 throw new SlcException("Cannot get celle editor", e
);