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