]> git.argeo.org Git - gpl/argeo-slc.git/blob - eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessBuilderPage.java
Improve imports
[gpl/argeo-slc.git] / eclipse / plugins / org.argeo.slc.client.ui / src / main / java / org / argeo / slc / client / ui / editors / ProcessBuilderPage.java
1 package org.argeo.slc.client.ui.editors;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.SortedSet;
7 import java.util.TreeSet;
8 import java.util.UUID;
9
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;
21
22 import org.argeo.ArgeoException;
23 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
24 import org.argeo.jcr.JcrUtils;
25 import org.argeo.slc.SlcException;
26 import org.argeo.slc.client.ui.SlcImages;
27 import org.argeo.slc.core.execution.PrimitiveUtils;
28 import org.argeo.slc.execution.ExecutionProcess;
29 import org.argeo.slc.jcr.SlcJcrUtils;
30 import org.argeo.slc.jcr.SlcNames;
31 import org.argeo.slc.jcr.SlcTypes;
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.EditingSupport;
36 import org.eclipse.jface.viewers.ISelectionChangedListener;
37 import org.eclipse.jface.viewers.IStructuredContentProvider;
38 import org.eclipse.jface.viewers.IStructuredSelection;
39 import org.eclipse.jface.viewers.ITreeContentProvider;
40 import org.eclipse.jface.viewers.SelectionChangedEvent;
41 import org.eclipse.jface.viewers.StructuredSelection;
42 import org.eclipse.jface.viewers.TableViewer;
43 import org.eclipse.jface.viewers.TableViewerColumn;
44 import org.eclipse.jface.viewers.TextCellEditor;
45 import org.eclipse.jface.viewers.TreeViewer;
46 import org.eclipse.jface.viewers.Viewer;
47 import org.eclipse.jface.viewers.ViewerDropAdapter;
48 import org.eclipse.swt.SWT;
49 import org.eclipse.swt.custom.SashForm;
50 import org.eclipse.swt.dnd.DND;
51 import org.eclipse.swt.dnd.TextTransfer;
52 import org.eclipse.swt.dnd.Transfer;
53 import org.eclipse.swt.dnd.TransferData;
54 import org.eclipse.swt.events.SelectionEvent;
55 import org.eclipse.swt.events.SelectionListener;
56 import org.eclipse.swt.graphics.Image;
57 import org.eclipse.swt.layout.FillLayout;
58 import org.eclipse.swt.layout.GridData;
59 import org.eclipse.swt.layout.GridLayout;
60 import org.eclipse.swt.layout.RowData;
61 import org.eclipse.swt.layout.RowLayout;
62 import org.eclipse.swt.widgets.Button;
63 import org.eclipse.swt.widgets.Composite;
64 import org.eclipse.swt.widgets.Label;
65 import org.eclipse.swt.widgets.Table;
66 import org.eclipse.ui.IWorkbenchPage;
67 import org.eclipse.ui.PlatformUI;
68 import org.eclipse.ui.forms.AbstractFormPart;
69 import org.eclipse.ui.forms.IManagedForm;
70 import org.eclipse.ui.forms.editor.FormPage;
71 import org.eclipse.ui.forms.widgets.FormToolkit;
72 import org.eclipse.ui.forms.widgets.ScrolledForm;
73
74 public class ProcessBuilderPage extends FormPage implements SlcNames {
75 public final static String ID = "processBuilderPage";
76 // private final static Log log =
77 // LogFactory.getLog(ProcessBuilderPage.class);
78
79 private Node processNode;
80
81 private TreeViewer flowsViewer;
82 private TableViewer valuesViewer;
83 private Label statusLabel;
84 private Button run;
85 private Button remove;
86 private Button clear;
87
88 private AbstractFormPart formPart;
89 private EventListener statusObserver;
90
91 public ProcessBuilderPage(ProcessEditor editor, Node processNode) {
92 super(editor, ID, "Definition");
93 this.processNode = processNode;
94 }
95
96 @Override
97 protected void createFormContent(IManagedForm mf) {
98 try {
99 ScrolledForm form = mf.getForm();
100 form.setExpandHorizontal(true);
101 form.setExpandVertical(true);
102 form.setText("Process " + processNode.getName());
103 GridLayout mainLayout = new GridLayout(1, true);
104 form.getBody().setLayout(mainLayout);
105
106 createControls(form.getBody());
107 createBuilder(form.getBody());
108
109 // form
110 formPart = new AbstractFormPart() {
111
112 };
113 getManagedForm().addPart(formPart);
114
115 // observation
116 statusObserver = new AsyncUiEventListener(form.getDisplay()) {
117 protected void onEventInUiThread(List<Event> events) {
118 statusChanged();
119 }
120 };
121 ObservationManager observationManager = processNode.getSession()
122 .getWorkspace().getObservationManager();
123 observationManager.addEventListener(statusObserver,
124 Event.PROPERTY_CHANGED, processNode.getPath(), true, null,
125 null, false);
126
127 // add initial flows
128 addInitialFlows();
129
130 } catch (RepositoryException e) {
131 throw new ArgeoException("Cannot create form content", e);
132 }
133 }
134
135 protected void createControls(Composite parent) {
136 FormToolkit tk = getManagedForm().getToolkit();
137
138 Composite controls = tk.createComposite(parent);
139 controls.setLayout(new RowLayout());
140 controls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
141
142 run = tk.createButton(controls, null, SWT.PUSH);
143 run.setToolTipText("Run");
144 run.setImage(SlcImages.LAUNCH);
145 run.addSelectionListener(new SelectionListener() {
146 public void widgetSelected(SelectionEvent e) {
147 if (isFinished(getProcessStatus())) {
148 relaunch();
149 } else {
150 ((ProcessEditor) getEditor()).process();
151 }
152 }
153
154 public void widgetDefaultSelected(SelectionEvent e) {
155 widgetSelected(e);
156 }
157 });
158
159 remove = tk.createButton(controls, null, SWT.PUSH);
160 remove.setImage(SlcImages.REMOVE_ONE);
161 remove.setToolTipText("Remove selected flows");
162 remove.addSelectionListener(new SelectionListener() {
163 public void widgetSelected(SelectionEvent e) {
164 removeSelectedFlows();
165 }
166
167 public void widgetDefaultSelected(SelectionEvent e) {
168 widgetSelected(e);
169 }
170 });
171
172 clear = tk.createButton(controls, null, SWT.PUSH);
173 clear.setImage(SlcImages.REMOVE_ALL);
174 clear.setToolTipText("Clear all flows");
175 clear.addSelectionListener(new SelectionListener() {
176 public void widgetSelected(SelectionEvent e) {
177 removeAllFlows();
178 }
179
180 public void widgetDefaultSelected(SelectionEvent e) {
181 widgetSelected(e);
182 }
183 });
184
185 Composite statusComposite = tk.createComposite(controls);
186 RowData rowData = new RowData();
187 rowData.width = 100;
188 rowData.height = 16;
189 statusComposite.setLayoutData(rowData);
190 statusComposite.setLayout(new FillLayout());
191 statusLabel = tk.createLabel(statusComposite, getProcessStatus());
192
193 // make sure all controls are in line with status
194 statusChanged();
195 }
196
197 protected void createBuilder(Composite parent) {
198 FormToolkit tk = getManagedForm().getToolkit();
199 SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL);
200 sashForm.setSashWidth(4);
201 GridData sahFormGd = new GridData(SWT.FILL, SWT.FILL, true, true);
202 sahFormGd.widthHint = 400;
203 sashForm.setLayoutData(sahFormGd);
204
205 Composite flowsComposite = tk.createComposite(sashForm);
206 flowsComposite.setLayout(new GridLayout(1, false));
207
208 flowsViewer = new TreeViewer(flowsComposite);
209 flowsViewer.getTree().setLayoutData(
210 new GridData(SWT.FILL, SWT.FILL, true, true));
211 flowsViewer.setLabelProvider(new FlowsLabelProvider());
212 flowsViewer.setContentProvider(new FlowsContentProvider());
213 flowsViewer.addSelectionChangedListener(new FlowsSelectionListener());
214
215 int operations = DND.DROP_COPY | DND.DROP_MOVE;
216 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
217 flowsViewer.addDropSupport(operations, tt, new FlowsDropListener(
218 flowsViewer));
219
220 flowsViewer.setInput(getEditorSite());
221 flowsViewer.setInput(processNode);
222
223 Composite valuesComposite = tk.createComposite(sashForm);
224 valuesComposite.setLayout(new GridLayout(1, false));
225
226 valuesViewer = new TableViewer(valuesComposite);
227 GridData valuedGd = new GridData(SWT.FILL, SWT.FILL, true, true);
228 // valuedGd.widthHint = 200;
229 valuesViewer.getTable().setLayoutData(valuedGd);
230 valuesViewer.setContentProvider(new ValuesContentProvider());
231 initializeValuesViewer(valuesViewer);
232 sashForm.setWeights(getWeights());
233 valuesViewer.setInput(getEditorSite());
234 }
235
236 /** Creates the columns of the values viewer */
237 protected void initializeValuesViewer(TableViewer viewer) {
238 String[] titles = { "Name", "Value" };
239 int[] bounds = { 200, 100 };
240
241 for (int i = 0; i < titles.length; i++) {
242 TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
243 column.getColumn().setText(titles[i]);
244 column.getColumn().setWidth(bounds[i]);
245 column.getColumn().setResizable(true);
246 column.getColumn().setMoveable(true);
247 if (i == 0) {
248 column.setLabelProvider(new ColumnLabelProvider() {
249 public String getText(Object element) {
250 try {
251 Node specAttrNode = (Node) element;
252 return specAttrNode.getName();
253 } catch (RepositoryException e) {
254 throw new SlcException("Cannot get value", e);
255 }
256 }
257 });
258 } else if (i == 1) {
259 column.setLabelProvider(new ColumnLabelProvider() {
260 public String getText(Object element) {
261 Object obj = getAttributeSpecValue((Node) element);
262 return obj != null ? obj.toString() : "";
263 }
264 });
265 column.setEditingSupport(new ValuesEditingSupport(viewer));
266 }
267
268 }
269 Table table = viewer.getTable();
270 table.setHeaderVisible(false);
271 table.setLinesVisible(true);
272 }
273
274 protected int[] getWeights() {
275 return new int[] { 50, 50 };
276 }
277
278 /*
279 * CONTROLLERS
280 */
281 /** Opens a new editor with a copy of this process */
282 protected void relaunch() {
283 try {
284 Node duplicatedNode = duplicateProcess();
285 IWorkbenchPage activePage = PlatformUI.getWorkbench()
286 .getActiveWorkbenchWindow().getActivePage();
287 activePage.openEditor(
288 new ProcessEditorInput(duplicatedNode.getPath()),
289 ProcessEditor.ID);
290 getEditor().close(false);
291 } catch (Exception e1) {
292 throw new SlcException("Cannot relaunch " + processNode, e1);
293 }
294 }
295
296 /** Duplicates the process */
297 protected Node duplicateProcess() {
298 try {
299 Session session = processNode.getSession();
300 String uuid = UUID.randomUUID().toString();
301 String destPath = SlcJcrUtils.createExecutionProcessPath(uuid);
302 Node newNode = JcrUtils.mkdirs(session, destPath,
303 SlcTypes.SLC_PROCESS);
304 JcrUtils.copy(processNode, newNode);
305 // session.getWorkspace().copy(processNode.getPath(), destPath);
306 // Node newNode = session.getNode(destPath);
307 // make sure that we kept the mixins
308 // newNode.addMixin(NodeType.MIX_CREATED);
309 // newNode.addMixin(NodeType.MIX_LAST_MODIFIED);
310 newNode.setProperty(SLC_UUID, uuid);
311 newNode.setProperty(SLC_STATUS, ExecutionProcess.INITIALIZED);
312 session.save();
313 return newNode;
314 } catch (RepositoryException e) {
315 throw new SlcException("Cannot duplicate process", e);
316 }
317 }
318
319 /** Reflects a status change */
320 protected void statusChanged() {
321 String status = getProcessStatus();
322 statusLabel.setText(status);
323 Boolean isEditable = isEditable(status);
324 run.setEnabled(isEditable);
325 remove.setEnabled(isEditable);
326 clear.setEnabled(isEditable);
327 // flowsViewer.getTree().setEnabled(isEditable);
328 if (status.equals(ExecutionProcess.COMPLETED)
329 || status.equals(ExecutionProcess.ERROR)) {
330 run.setEnabled(true);
331 run.setImage(SlcImages.RELAUNCH);
332 run.setToolTipText("Relaunch");
333 }
334 }
335
336 /** Adds initial flows from the editor input if any */
337 protected void addInitialFlows() {
338 for (String path : ((ProcessEditorInput) getEditorInput())
339 .getInitialFlowPaths()) {
340 addFlow(path);
341 }
342 }
343
344 /**
345 * Adds a new flow.
346 *
347 * @param path
348 * the path of the flow
349 */
350 protected void addFlow(String path) {
351 try {
352 Node flowNode = processNode.getSession().getNode(path);
353 Node realizedFlowNode = processNode.getNode(SLC_FLOW).addNode(
354 SLC_FLOW);
355 realizedFlowNode.addMixin(SlcTypes.SLC_REALIZED_FLOW);
356 Node address = realizedFlowNode.addNode(SLC_ADDRESS,
357 NodeType.NT_ADDRESS);
358 address.setProperty(Property.JCR_PATH, path);
359
360 // copy spec attributes
361 Node specAttrsBase;
362 if (flowNode.hasProperty(SLC_SPEC)) {
363 Node executionSpecNode = flowNode.getProperty(SLC_SPEC)
364 .getNode();
365 specAttrsBase = executionSpecNode;
366 String executionSpecName = executionSpecNode.getProperty(
367 SLC_NAME).getString();
368 realizedFlowNode.setProperty(SLC_SPEC, executionSpecName);
369 } else
370 specAttrsBase = flowNode;
371
372 specAttrs: for (NodeIterator nit = specAttrsBase.getNodes(); nit
373 .hasNext();) {
374 Node specAttrNode = nit.nextNode();
375 String attrName = specAttrNode.getName();
376 if (!specAttrNode
377 .isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
378 continue specAttrs;
379 Node realizedAttrNode = realizedFlowNode.addNode(specAttrNode
380 .getName());
381 JcrUtils.copy(specAttrNode, realizedAttrNode);
382
383 // ovveride with flow value
384 if (flowNode.hasNode(attrName)) {
385 // assuming this is a primitive
386 realizedAttrNode.setProperty(SLC_VALUE,
387 flowNode.getNode(attrName).getProperty(SLC_VALUE)
388 .getValue());
389 }
390 }
391
392 flowsViewer.refresh();
393 formPart.markDirty();
394 } catch (RepositoryException e) {
395 throw new SlcException("Cannot drop " + path, e);
396 }
397 }
398
399 @SuppressWarnings("unchecked")
400 protected void removeSelectedFlows() {
401 if (!flowsViewer.getSelection().isEmpty()) {
402 Iterator<Object> it = ((StructuredSelection) flowsViewer
403 .getSelection()).iterator();
404 while (it.hasNext()) {
405 Node node = (Node) it.next();
406 try {
407 node.remove();
408 } catch (RepositoryException e) {
409 throw new ArgeoException("Cannot remove " + node, e);
410 }
411 }
412 flowsViewer.refresh();
413 formPart.markDirty();
414 }
415 }
416
417 protected void removeAllFlows() {
418 try {
419 for (NodeIterator nit = processNode.getNode(SLC_FLOW).getNodes(); nit
420 .hasNext();) {
421 nit.nextNode().remove();
422 }
423 flowsViewer.refresh();
424 formPart.markDirty();
425 } catch (RepositoryException e) {
426 throw new ArgeoException("Cannot remove flows from " + processNode,
427 e);
428 }
429 }
430
431 public void commit(Boolean onSave) {
432 if (onSave)
433 statusLabel.setText(getProcessStatus());
434 formPart.commit(onSave);
435 }
436
437 /*
438 * STATE
439 */
440 protected String getProcessStatus() {
441 try {
442 return processNode.getProperty(SLC_STATUS).getString();
443 } catch (RepositoryException e) {
444 throw new SlcException("Cannot retrieve status for " + processNode,
445 e);
446 }
447 }
448
449 /** Optimization so that we don't call the node each time */
450 protected Boolean isEditable(String status) {
451 return status.equals(ExecutionProcess.NEW)
452 || status.equals(ExecutionProcess.INITIALIZED);
453 }
454
455 protected Boolean isFinished(String status) {
456 return status.equals(ExecutionProcess.COMPLETED)
457 || status.equals(ExecutionProcess.ERROR);
458 }
459
460 /*
461 * LIFECYCLE
462 */
463 @Override
464 public void dispose() {
465 JcrUtils.unregisterQuietly(processNode, statusObserver);
466 super.dispose();
467 }
468
469 /*
470 * UTILITIES
471 */
472 protected static Object getAttributeSpecValue(Node specAttrNode) {
473 try {
474 if (specAttrNode.isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
475 if (!specAttrNode.hasProperty(SLC_VALUE))
476 return null;
477 String type = specAttrNode.getProperty(SLC_TYPE).getString();
478 // TODO optimize based on data type?
479 Object value = PrimitiveUtils.convert(type, specAttrNode
480 .getProperty(SLC_VALUE).getString());
481 // log.debug(specAttrNode + ", type=" + type + ", value=" +
482 // value);
483 return value;
484 }
485 return null;
486 } catch (RepositoryException e) {
487 throw new SlcException("Cannot get value", e);
488 }
489
490 }
491
492 /*
493 * FLOWS SUBCLASSES
494 */
495 static class FlowsContentProvider implements ITreeContentProvider {
496 public Object[] getElements(Object obj) {
497 if (!(obj instanceof Node))
498 return new Object[0];
499
500 try {
501 Node node = (Node) obj;
502 List<Node> children = new ArrayList<Node>();
503 for (NodeIterator nit = node.getNode(SLC_FLOW).getNodes(); nit
504 .hasNext();)
505 children.add(nit.nextNode());
506 return children.toArray();
507 } catch (RepositoryException e) {
508 throw new SlcException("Cannot list children of " + obj, e);
509 }
510 }
511
512 public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
513 }
514
515 public void dispose() {
516 }
517
518 public Object[] getChildren(Object parentElement) {
519 // no children for the time being
520 return null;
521 }
522
523 public Object getParent(Object element) {
524 return null;
525 }
526
527 public boolean hasChildren(Object element) {
528 return false;
529 }
530
531 }
532
533 static class FlowsLabelProvider extends ColumnLabelProvider {
534
535 @Override
536 public String getText(Object element) {
537 Node node = (Node) element;
538 try {
539 if (node.isNodeType(SlcTypes.SLC_REALIZED_FLOW)) {
540 if (node.hasNode(SLC_ADDRESS)) {
541 String path = node.getNode(SLC_ADDRESS)
542 .getProperty(Property.JCR_PATH).getString();
543 return SlcJcrUtils.flowExecutionModuleName(path) + ":"
544 + SlcJcrUtils.flowRelativePath(path);
545 }
546 }
547 } catch (RepositoryException e) {
548 throw new SlcException("Cannot display " + element, e);
549 }
550 return super.getText(element);
551 }
552
553 @Override
554 public Image getImage(Object element) {
555 Node node = (Node) element;
556 try {
557 if (node.isNodeType(SlcTypes.SLC_REALIZED_FLOW)) {
558 return SlcImages.FLOW;
559 }
560 } catch (RepositoryException e) {
561 throw new SlcException("Cannot display " + element, e);
562 }
563 return super.getImage(element);
564 }
565
566 }
567
568 /** Parameter view is updated each time a new line is selected */
569 class FlowsSelectionListener implements ISelectionChangedListener {
570 public void selectionChanged(SelectionChangedEvent evt) {
571 if (evt.getSelection().isEmpty()) {
572 valuesViewer.setInput(getEditorSite());
573 return;
574 }
575 Node realizedFlowNode = (Node) ((IStructuredSelection) evt
576 .getSelection()).getFirstElement();
577 valuesViewer.setInput(realizedFlowNode);
578 }
579 }
580
581 /** Manages drop event. */
582 class FlowsDropListener extends ViewerDropAdapter {
583
584 public FlowsDropListener(Viewer viewer) {
585 super(viewer);
586 }
587
588 @Override
589 public boolean performDrop(Object data) {
590 String path = data.toString();
591 try {
592 // either a node or a whole directory was dragged
593 QueryManager qm = processNode.getSession().getWorkspace()
594 .getQueryManager();
595 String statement = "SELECT * FROM ["
596 + SlcTypes.SLC_EXECUTION_FLOW
597 + "] WHERE ISDESCENDANTNODE(['" + path
598 + "']) OR ISSAMENODE(['" + path + "'])";
599 // log.debug(statement);
600 Query query = qm.createQuery(statement, Query.JCR_SQL2);
601
602 // order paths
603 SortedSet<String> paths = new TreeSet<String>();
604 for (NodeIterator nit = query.execute().getNodes(); nit
605 .hasNext();) {
606 paths.add(nit.nextNode().getPath());
607 }
608
609 for (String p : paths) {
610 addFlow(p);
611 }
612 return true;
613 } catch (RepositoryException e) {
614 throw new SlcException("Cannot query flows under " + path, e);
615 }
616 }
617
618 @Override
619 public boolean validateDrop(Object target, int operation,
620 TransferData transferType) {
621 return isEditable(getProcessStatus());
622 }
623 }
624
625 /*
626 * VALUES SUBCLASSES
627 */
628 static class ValuesContentProvider implements IStructuredContentProvider {
629
630 public Object[] getElements(Object inputElement) {
631 if (!(inputElement instanceof Node))
632 return new Object[0];
633
634 try {
635 Node realizedFlowNode = (Node) inputElement;
636 List<Node> specAttributes = new ArrayList<Node>();
637 specAttrs: for (NodeIterator nit = realizedFlowNode.getNodes(); nit
638 .hasNext();) {
639 Node specAttrNode = nit.nextNode();
640 if (!specAttrNode
641 .isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
642 continue specAttrs;
643 specAttributes.add(specAttrNode);
644 }
645 return specAttributes.toArray();
646 } catch (RepositoryException e) {
647 throw new SlcException("Cannot get elements", e);
648 }
649 }
650
651 public void dispose() {
652 }
653
654 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
655 }
656 }
657
658 class ValuesEditingSupport extends EditingSupport {
659 private final TableViewer tableViewer;
660
661 public ValuesEditingSupport(ColumnViewer viewer) {
662 super(viewer);
663 tableViewer = (TableViewer) viewer;
664 }
665
666 @Override
667 protected CellEditor getCellEditor(Object element) {
668 try {
669 Node specAttrNode = (Node) element;
670 if (specAttrNode
671 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE))
672 return new TextCellEditor(tableViewer.getTable());
673 return null;
674 } catch (RepositoryException e) {
675 throw new SlcException("Cannot get celle editor", e);
676 }
677 }
678
679 @Override
680 protected boolean canEdit(Object element) {
681 try {
682 Node specAttrNode = (Node) element;
683 return !(specAttrNode.getProperty(SLC_IS_IMMUTABLE)
684 .getBoolean() || specAttrNode.getProperty(
685 SLC_IS_CONSTANT).getBoolean())
686 && specAttrNode
687 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
688 } catch (RepositoryException e) {
689 throw new SlcException("Cannot check canEdit", e);
690 }
691 }
692
693 @Override
694 protected Object getValue(Object element) {
695 Node specAttrNode = (Node) element;
696 try {
697 Object value = getAttributeSpecValue(specAttrNode);
698 if (value == null)
699 throw new SlcException("Unsupported attribute " + element);
700 if (specAttrNode
701 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE))
702 return value.toString();
703 return value;
704 } catch (RepositoryException e) {
705 throw new SlcException("Cannot get value for " + element, e);
706 }
707 }
708
709 @Override
710 protected void setValue(Object element, Object value) {
711 try {
712 Node specAttrNode = (Node) element;
713 if (specAttrNode
714 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
715 String type = specAttrNode.getProperty(SLC_TYPE)
716 .getString();
717 SlcJcrUtils.setPrimitiveAsProperty(specAttrNode, SLC_VALUE,
718 type, value);
719 valuesViewer.refresh();
720 formPart.markDirty();
721 }
722 } catch (RepositoryException e) {
723 throw new SlcException("Cannot get celle editor", e);
724 }
725 }
726
727 }
728 }