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