1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.argeo.slc.client.ui.editors;
17
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;
23
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;
34
35 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
36 import org.argeo.jcr.JcrUtils;
37 import org.argeo.slc.SlcException;
38 import org.argeo.slc.SlcNames;
39 import org.argeo.slc.SlcTypes;
40 import org.argeo.slc.client.ui.SlcImages;
41 import org.argeo.slc.core.execution.PrimitiveAccessor;
42 import org.argeo.slc.core.execution.PrimitiveUtils;
43 import org.argeo.slc.execution.ExecutionProcess;
44 import org.argeo.slc.jcr.SlcJcrUtils;
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.Menu;
80 import org.eclipse.swt.widgets.MenuItem;
81 import org.eclipse.swt.widgets.Table;
82 import org.eclipse.ui.forms.AbstractFormPart;
83 import org.eclipse.ui.forms.IManagedForm;
84 import org.eclipse.ui.forms.editor.FormPage;
85 import org.eclipse.ui.forms.widgets.FormToolkit;
86 import org.eclipse.ui.forms.widgets.ScrolledForm;
87
88
89 public class ProcessBuilderPage extends FormPage implements SlcNames {
90
91
92
93 public final static String ID = "processBuilderPage";
94
95
96 final static String NONE = "<none>";
97
98 private Node processNode;
99
100 private TreeViewer flowsViewer;
101 private TableViewer valuesViewer;
102 private Label statusLabel;
103 private Button run;
104 private Button remove;
105 private Button clear;
106
107 private AbstractFormPart formPart;
108 private EventListener statusObserver;
109
110 public ProcessBuilderPage(ProcessEditor editor, Node processNode) {
111 super(editor, ID, "Definition");
112 this.processNode = processNode;
113 }
114
115 @Override
116 protected void createFormContent(IManagedForm mf) {
117 try {
118 ScrolledForm form = mf.getForm();
119 form.setExpandHorizontal(true);
120 form.setExpandVertical(true);
121 form.setText("Process " + processNode.getName());
122 GridLayout mainLayout = new GridLayout(1, true);
123 form.getBody().setLayout(mainLayout);
124
125 createControls(form.getBody());
126 createBuilder(form.getBody());
127
128
129 formPart = new AbstractFormPart() {
130
131 };
132 getManagedForm().addPart(formPart);
133
134
135 statusObserver = new AsyncUiEventListener(form.getDisplay()) {
136 protected void onEventInUiThread(List<Event> events) {
137 statusChanged();
138 }
139 };
140 ObservationManager observationManager = processNode.getSession()
141 .getWorkspace().getObservationManager();
142 observationManager.addEventListener(statusObserver,
143 Event.PROPERTY_CHANGED, processNode.getPath(), true, null,
144 null, false);
145
146
147 statusChanged();
148
149
150 addInitialFlows();
151
152 } catch (RepositoryException e) {
153 throw new SlcException("Cannot create form content", e);
154 }
155 }
156
157 protected void createControls(Composite parent) {
158 FormToolkit tk = getManagedForm().getToolkit();
159
160 Composite controls = tk.createComposite(parent);
161 controls.setLayout(new RowLayout());
162 controls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
163
164 run = tk.createButton(controls, null, SWT.PUSH);
165 run.setToolTipText("Run");
166 run.setImage(SlcImages.LAUNCH);
167 run.addSelectionListener(new SelectionListener() {
168 public void widgetSelected(SelectionEvent e) {
169 if (isFinished(getProcessStatus())) {
170 ((ProcessEditor) getEditor()).relaunch();
171 } else if (isRunning(getProcessStatus())) {
172 ((ProcessEditor) getEditor()).kill();
173 } else {
174 ((ProcessEditor) getEditor()).process();
175 }
176 }
177
178 public void widgetDefaultSelected(SelectionEvent e) {
179 widgetSelected(e);
180 }
181 });
182
183 remove = tk.createButton(controls, null, SWT.PUSH);
184 remove.setImage(SlcImages.REMOVE_ONE);
185 remove.setToolTipText("Remove selected flows");
186 remove.addSelectionListener(new SelectionListener() {
187 public void widgetSelected(SelectionEvent e) {
188 removeSelectedFlows();
189 }
190
191 public void widgetDefaultSelected(SelectionEvent e) {
192 widgetSelected(e);
193 }
194 });
195
196 clear = tk.createButton(controls, null, SWT.PUSH);
197 clear.setImage(SlcImages.REMOVE_ALL);
198 clear.setToolTipText("Clear all flows");
199 clear.addSelectionListener(new SelectionListener() {
200 public void widgetSelected(SelectionEvent e) {
201 removeAllFlows();
202 }
203
204 public void widgetDefaultSelected(SelectionEvent e) {
205 widgetSelected(e);
206 }
207 });
208
209 Composite statusComposite = tk.createComposite(controls);
210 RowData rowData = new RowData();
211 rowData.width = 100;
212 rowData.height = 16;
213 statusComposite.setLayoutData(rowData);
214 statusComposite.setLayout(new FillLayout());
215 statusLabel = tk.createLabel(statusComposite, getProcessStatus());
216
217 }
218
219 protected void createBuilder(Composite parent) {
220 FormToolkit tk = getManagedForm().getToolkit();
221 SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL);
222 sashForm.setSashWidth(4);
223 GridData sahFormGd = new GridData(SWT.FILL, SWT.FILL, true, true);
224 sahFormGd.widthHint = 400;
225 sashForm.setLayoutData(sahFormGd);
226
227 Composite flowsComposite = tk.createComposite(sashForm);
228 flowsComposite.setLayout(new GridLayout(1, false));
229
230 flowsViewer = new TreeViewer(flowsComposite);
231 flowsViewer.getTree().setLayoutData(
232 new GridData(SWT.FILL, SWT.FILL, true, true));
233 flowsViewer.setLabelProvider(new FlowsLabelProvider());
234 flowsViewer.setContentProvider(new FlowsContentProvider());
235 flowsViewer.addSelectionChangedListener(new FlowsSelectionListener());
236
237 int operations = DND.DROP_COPY | DND.DROP_MOVE;
238 Transfer[] tt = new Transfer[] { TextTransfer.getInstance() };
239 flowsViewer.addDropSupport(operations, tt, new FlowsDropListener(
240 flowsViewer));
241
242
243 addContextMenu();
244
245 flowsViewer.setInput(getEditorSite());
246 flowsViewer.setInput(processNode);
247
248 Composite valuesComposite = tk.createComposite(sashForm);
249 valuesComposite.setLayout(new GridLayout(1, false));
250
251 valuesViewer = new TableViewer(valuesComposite);
252 GridData valuedGd = new GridData(SWT.FILL, SWT.FILL, true, true);
253
254 valuesViewer.getTable().setLayoutData(valuedGd);
255 valuesViewer.getTable().setHeaderVisible(true);
256
257 valuesViewer.setContentProvider(new ValuesContentProvider());
258 initializeValuesViewer(valuesViewer);
259 sashForm.setWeights(getWeights());
260 valuesViewer.setInput(getEditorSite());
261 }
262
263
264 protected void initializeValuesViewer(TableViewer viewer) {
265 String[] titles = { "Name", "Value" };
266 int[] bounds = { 200, 100 };
267
268 for (int i = 0; i < titles.length; i++) {
269 TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
270 column.getColumn().setText(titles[i]);
271 column.getColumn().setWidth(bounds[i]);
272 column.getColumn().setResizable(true);
273 column.getColumn().setMoveable(true);
274 if (i == 0) {
275 column.setLabelProvider(new ColumnLabelProvider() {
276 public String getText(Object element) {
277 try {
278 Node specAttrNode = (Node) element;
279 return specAttrNode.getName();
280 } catch (RepositoryException e) {
281 throw new SlcException("Cannot get value", e);
282 }
283 }
284 });
285 } else if (i == 1) {
286 column.setLabelProvider(new ColumnLabelProvider() {
287 public String getText(Object element) {
288 return getAttributeSpecText((Node) element);
289 }
290 });
291 column.setEditingSupport(new ValuesEditingSupport(viewer));
292 }
293
294 }
295 Table table = viewer.getTable();
296 table.setHeaderVisible(false);
297 table.setLinesVisible(true);
298 }
299
300 protected int[] getWeights() {
301 return new int[] { 50, 50 };
302 }
303
304
305
306
307
308 protected void statusChanged() {
309 String status = getProcessStatus();
310 statusLabel.setText(status);
311 Boolean isEditable = isEditable(status);
312 run.setEnabled(status.equals(ExecutionProcess.RUNNING) || isEditable);
313 remove.setEnabled(isEditable);
314 clear.setEnabled(isEditable);
315
316 if (status.equals(ExecutionProcess.RUNNING)) {
317 run.setEnabled(true);
318 run.setImage(SlcImages.KILL);
319 run.setToolTipText("Kill");
320 } else if (isFinished(status)) {
321 run.setEnabled(true);
322 run.setImage(SlcImages.RELAUNCH);
323 run.setToolTipText("Relaunch");
324 }
325
326 if (flowsViewer != null)
327 flowsViewer.refresh();
328 }
329
330
331 protected void addInitialFlows() {
332 for (String path : ((ProcessEditorInput) getEditorInput())
333 .getInitialFlowPaths()) {
334 addFlow(path);
335 }
336 }
337
338
339
340
341
342
343
344 protected void addFlow(String path) {
345 try {
346 Node flowNode = processNode.getSession().getNode(path);
347 Node realizedFlowNode = processNode.getNode(SLC_FLOW).addNode(
348 SLC_FLOW);
349 realizedFlowNode.setProperty(SLC_NAME,
350 flowNode.getProperty(SLC_NAME).getString());
351 realizedFlowNode.addMixin(SlcTypes.SLC_REALIZED_FLOW);
352 Node address = realizedFlowNode.addNode(SLC_ADDRESS,
353 NodeType.NT_ADDRESS);
354 address.setProperty(Property.JCR_PATH, path);
355
356
357 Node specAttrsBase;
358 if (flowNode.hasProperty(SLC_SPEC)) {
359 Node executionSpecNode = flowNode.getProperty(SLC_SPEC)
360 .getNode();
361 specAttrsBase = executionSpecNode;
362 String executionSpecName = executionSpecNode.getProperty(
363 SLC_NAME).getString();
364 realizedFlowNode.setProperty(SLC_SPEC, executionSpecName);
365 } else
366 specAttrsBase = flowNode;
367
368 specAttrs: for (NodeIterator nit = specAttrsBase.getNodes(); nit
369 .hasNext();) {
370 Node specAttrNode = nit.nextNode();
371 String attrName = specAttrNode.getName();
372 if (!specAttrNode
373 .isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
374 continue specAttrs;
375 Node realizedAttrNode = realizedFlowNode.addNode(specAttrNode
376 .getName());
377 JcrUtils.copy(specAttrNode, realizedAttrNode);
378
379
380 if (flowNode.hasNode(attrName)) {
381
382 Node attrNode = flowNode.getNode(attrName);
383 if (attrNode.hasProperty(SLC_VALUE))
384 realizedAttrNode.setProperty(SLC_VALUE, attrNode
385 .getProperty(SLC_VALUE).getValue());
386 }
387 }
388
389
390 StringBuilder editorTitle = new StringBuilder();
391 NodeIterator it = realizedFlowNode.getParent().getNodes(SLC_FLOW);
392 while (it.hasNext()) {
393 Node rFlowNode = it.nextNode();
394 String name = rFlowNode.getProperty(SLC_NAME).getString();
395 editorTitle.append(name).append(' ');
396 }
397 ((ProcessEditor) getEditor())
398 .setEditorTitle(editorTitle.toString());
399
400 flowsViewer.refresh();
401 formPart.markDirty();
402 } catch (RepositoryException e) {
403 throw new SlcException("Cannot add flow " + path, e);
404 }
405 }
406
407 @SuppressWarnings("unchecked")
408 protected void removeSelectedFlows() {
409 if (!flowsViewer.getSelection().isEmpty()) {
410 Iterator<Object> it = ((StructuredSelection) flowsViewer
411 .getSelection()).iterator();
412 while (it.hasNext()) {
413 Node node = (Node) it.next();
414 try {
415 node.remove();
416 } catch (RepositoryException e) {
417 throw new SlcException("Cannot remove " + node, e);
418 }
419 }
420 flowsViewer.refresh();
421 formPart.markDirty();
422 }
423 }
424
425 protected void removeAllFlows() {
426 try {
427 for (NodeIterator nit = processNode.getNode(SLC_FLOW).getNodes(); nit
428 .hasNext();) {
429 nit.nextNode().remove();
430 }
431 flowsViewer.refresh();
432 formPart.markDirty();
433 } catch (RepositoryException e) {
434 throw new SlcException("Cannot remove flows from " + processNode,
435 e);
436 }
437 }
438
439 public void commit(Boolean onSave) {
440 if (onSave)
441 statusLabel.setText(getProcessStatus());
442 formPart.commit(onSave);
443 }
444
445
446
447
448 protected String getProcessStatus() {
449 try {
450 return processNode.getProperty(SLC_STATUS).getString();
451 } catch (RepositoryException e) {
452 throw new SlcException("Cannot retrieve status for " + processNode,
453 e);
454 }
455 }
456
457
458 protected static Boolean isEditable(String status) {
459 return status.equals(ExecutionProcess.NEW)
460 || status.equals(ExecutionProcess.INITIALIZED);
461 }
462
463 protected static Boolean isFinished(String status) {
464 return status.equals(ExecutionProcess.COMPLETED)
465 || status.equals(ExecutionProcess.ERROR)
466 || status.equals(ExecutionProcess.KILLED);
467 }
468
469 protected static Boolean isRunning(String status) {
470 return status.equals(ExecutionProcess.RUNNING);
471 }
472
473
474
475
476 @Override
477 public void dispose() {
478 JcrUtils.unregisterQuietly(processNode, statusObserver);
479 super.dispose();
480 }
481
482
483
484
485 protected static String getAttributeSpecText(Node specAttrNode) {
486 try {
487 if (specAttrNode.isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
488 if (!specAttrNode.hasProperty(SLC_VALUE))
489 return "";
490 String type = specAttrNode.getProperty(SLC_TYPE).getString();
491 if (PrimitiveAccessor.TYPE_PASSWORD.equals(type))
492 return "****************";
493 Object value = PrimitiveUtils.convert(type, specAttrNode
494 .getProperty(SLC_VALUE).getString());
495 return value.toString();
496 } else if (specAttrNode.isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
497 if (specAttrNode.hasProperty(SLC_VALUE)) {
498 int value = (int) specAttrNode.getProperty(SLC_VALUE)
499 .getLong();
500 NodeIterator children = specAttrNode.getNodes();
501 int index = 0;
502 while (children.hasNext()) {
503 Node child = children.nextNode();
504 if (index == value)
505 return child.getProperty(Property.JCR_TITLE)
506 .getString();
507 index++;
508 }
509 throw new SlcException("No child node with index " + value
510 + " for spec attribute " + specAttrNode);
511 } else
512 return "";
513 }
514 throw new SlcException("Unsupported type for spec attribute "
515 + specAttrNode);
516 } catch (RepositoryException e) {
517 throw new SlcException("Cannot get value", e);
518 }
519 }
520
521
522
523
524 class FlowsContentProvider implements ITreeContentProvider {
525 public Object[] getElements(Object obj) {
526 if (!(obj instanceof Node))
527 return new Object[0];
528
529 try {
530 Node node = (Node) obj;
531 List<Node> children = new ArrayList<Node>();
532 for (NodeIterator nit = node.getNode(SLC_FLOW).getNodes(); nit
533 .hasNext();) {
534 Node flowNode = nit.nextNode();
535 children.add(flowNode);
536 }
537 return children.toArray();
538 } catch (RepositoryException e) {
539 throw new SlcException("Cannot list flows of " + obj, e);
540 }
541 }
542
543 public void inputChanged(Viewer arg0, Object arg1, Object arg2) {
544 }
545
546 public void dispose() {
547 }
548
549 public Object[] getChildren(Object parentElement) {
550
551 return null;
552 }
553
554 public Object getParent(Object element) {
555 return null;
556 }
557
558 public boolean hasChildren(Object element) {
559 return false;
560 }
561
562 }
563
564 static class FlowsLabelProvider extends ColumnLabelProvider {
565 @Override
566 public String getText(Object element) {
567 Node node = (Node) element;
568 try {
569 if (node.isNodeType(SlcTypes.SLC_REALIZED_FLOW)) {
570 if (node.hasNode(SLC_ADDRESS)) {
571 String path = node.getNode(SLC_ADDRESS)
572 .getProperty(Property.JCR_PATH).getString();
573 String executionModuleName = SlcJcrUtils
574 .moduleName(path);
575
576
577
578
579 return executionModuleName + ":"
580 + SlcJcrUtils.flowRelativePath(path);
581 }
582 }
583 } catch (RepositoryException e) {
584 throw new SlcException("Cannot display " + element, e);
585 }
586 return super.getText(element);
587 }
588
589 @Override
590 public Image getImage(Object element) {
591 Node node = (Node) element;
592 try {
593 if (node.isNodeType(SlcTypes.SLC_REALIZED_FLOW)) {
594 if (node.hasProperty(SLC_STATUS)) {
595 String status = node.getProperty(SLC_STATUS)
596 .getString();
597
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;
605 }
606 return SlcImages.FLOW;
607 }
608 } catch (RepositoryException e) {
609 throw new SlcException("Cannot display " + element, e);
610 }
611 return super.getImage(element);
612 }
613
614 }
615
616
617 class FlowsSelectionListener implements ISelectionChangedListener {
618 public void selectionChanged(SelectionChangedEvent evt) {
619 if (evt.getSelection().isEmpty()) {
620 valuesViewer.setInput(getEditorSite());
621 return;
622 }
623 Node realizedFlowNode = (Node) ((IStructuredSelection) evt
624 .getSelection()).getFirstElement();
625 valuesViewer.setInput(realizedFlowNode);
626 }
627 }
628
629
630
631
632
633 private void addContextMenu() {
634 Menu menu = new Menu(flowsViewer.getControl());
635
636 MenuItem removeItems = new MenuItem(menu, SWT.PUSH);
637 removeItems.addSelectionListener(new SelectionListener() {
638
639 public void widgetSelected(SelectionEvent e) {
640 removeSelectedFlows();
641 }
642
643 public void widgetDefaultSelected(SelectionEvent e) {
644 }
645 });
646 removeItems.setText("Remove selected flow(s)");
647
648 MenuItem removeAllItems = new MenuItem(menu, SWT.PUSH);
649 removeAllItems.addSelectionListener(new SelectionListener() {
650
651 public void widgetSelected(SelectionEvent e) {
652 removeAllFlows();
653 }
654
655 public void widgetDefaultSelected(SelectionEvent e) {
656 }
657 });
658 removeAllItems.setText("Remove all flows");
659 flowsViewer.getTree().setMenu(menu);
660 }
661
662
663 class FlowsDropListener extends ViewerDropAdapter {
664
665 public FlowsDropListener(Viewer viewer) {
666 super(viewer);
667 }
668
669 @Override
670 public boolean performDrop(Object data) {
671
672
673
674 String[] paths = data.toString().split(new String("\n"));
675 SortedSet<String> resultPaths = new TreeSet<String>();
676 for (String path : paths) {
677 try {
678
679 QueryManager qm = processNode.getSession().getWorkspace()
680 .getQueryManager();
681 String statement = "SELECT * FROM ["
682 + SlcTypes.SLC_EXECUTION_FLOW
683 + "] WHERE ISDESCENDANTNODE(['" + path
684 + "']) OR ISSAMENODE(['" + path + "'])";
685 Query query = qm.createQuery(statement, Query.JCR_SQL2);
686
687
688 for (NodeIterator nit = query.execute().getNodes(); nit
689 .hasNext();) {
690 String currPath = nit.nextNode().getPath();
691
692 if (!resultPaths.contains(currPath))
693 resultPaths.add(currPath);
694 }
695 } catch (RepositoryException e) {
696 throw new SlcException("Cannot query flows under " + path,
697 e);
698 }
699 }
700 for (String p : resultPaths) {
701 addFlow(p);
702 }
703 return true;
704
705 }
706
707 @Override
708 public boolean validateDrop(Object target, int operation,
709 TransferData transferType) {
710 return isEditable(getProcessStatus());
711 }
712 }
713
714
715
716
717 static class ValuesContentProvider implements IStructuredContentProvider {
718
719 public Object[] getElements(Object inputElement) {
720 if (!(inputElement instanceof Node))
721 return new Object[0];
722
723 try {
724 Node realizedFlowNode = (Node) inputElement;
725 List<Node> specAttributes = new ArrayList<Node>();
726 specAttrs: for (NodeIterator nit = realizedFlowNode.getNodes(); nit
727 .hasNext();) {
728 Node specAttrNode = nit.nextNode();
729 if (!specAttrNode
730 .isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
731 continue specAttrs;
732
733
734 else if (specAttrNode.hasProperty(SlcNames.SLC_IS_HIDDEN)
735 && specAttrNode.getProperty(SlcNames.SLC_IS_HIDDEN)
736 .getBoolean())
737 continue specAttrs;
738 specAttributes.add(specAttrNode);
739 }
740 return specAttributes.toArray();
741 } catch (RepositoryException e) {
742 throw new SlcException("Cannot get elements", e);
743 }
744 }
745
746 public void dispose() {
747 }
748
749 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
750 }
751 }
752
753 class ValuesEditingSupport extends EditingSupport {
754 private final TableViewer tableViewer;
755
756 public ValuesEditingSupport(ColumnViewer viewer) {
757 super(viewer);
758 tableViewer = (TableViewer) viewer;
759 }
760
761 @Override
762 protected CellEditor getCellEditor(Object element) {
763 try {
764 Node specAttrNode = (Node) element;
765 if (specAttrNode
766 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
767 String type = specAttrNode.getProperty(SLC_TYPE)
768 .getString();
769 if (PrimitiveAccessor.TYPE_PASSWORD.equals(type)) {
770 return new TextCellEditor(tableViewer.getTable(),
771 SWT.PASSWORD);
772 } else {
773 return new TextCellEditor(tableViewer.getTable());
774 }
775 } else if (specAttrNode
776 .isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
777 NodeIterator children = specAttrNode.getNodes();
778 ArrayList<String> items = new ArrayList<String>();
779 while (children.hasNext()) {
780 Node child = children.nextNode();
781 if (child.isNodeType(NodeType.MIX_TITLE))
782 items.add(child.getProperty(Property.JCR_TITLE)
783 .getString());
784 }
785 return new ComboBoxCellEditor(tableViewer.getTable(),
786 items.toArray(new String[items.size()]));
787 }
788 return null;
789 } catch (RepositoryException e) {
790 throw new SlcException("Cannot get cell editor", e);
791 }
792 }
793
794 @Override
795 protected boolean canEdit(Object element) {
796 try {
797 Node specAttrNode = (Node) element;
798 Boolean cannotEdit = specAttrNode.getProperty(SLC_IS_IMMUTABLE)
799 .getBoolean()
800 || specAttrNode.getProperty(SLC_IS_CONSTANT)
801 .getBoolean();
802 return !cannotEdit && isSupportedAttributeType(specAttrNode);
803 } catch (RepositoryException e) {
804 throw new SlcException("Cannot check whether " + element
805 + " is editable", e);
806 }
807 }
808
809
810
811
812
813 protected boolean isSupportedAttributeType(Node specAttrNode)
814 throws RepositoryException {
815 return specAttrNode
816 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)
817 || specAttrNode.isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
818 }
819
820 @Override
821 protected Object getValue(Object element) {
822 Node specAttrNode = (Node) element;
823 try {
824 if (specAttrNode
825 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
826 if (!specAttrNode.hasProperty(SLC_VALUE))
827 return NONE;
828 String type = specAttrNode.getProperty(SLC_TYPE)
829 .getString();
830
831 Object value = PrimitiveUtils.convert(type, specAttrNode
832 .getProperty(SLC_VALUE).getString());
833 return value.toString();
834 } else if (specAttrNode
835 .isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
836 if (!specAttrNode.hasProperty(SLC_VALUE))
837 return 0;
838
839
840 return (int) specAttrNode.getProperty(SLC_VALUE).getLong();
841 }
842 throw new SlcException("Unsupported type for spec attribute "
843 + specAttrNode);
844 } catch (RepositoryException e) {
845 throw new SlcException("Cannot get value for " + element, e);
846 }
847 }
848
849 @Override
850 protected void setValue(Object element, Object value) {
851 try {
852 Node specAttrNode = (Node) element;
853 if (specAttrNode
854 .isNodeType(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE)) {
855 String type = specAttrNode.getProperty(SLC_TYPE)
856 .getString();
857 SlcJcrUtils.setPrimitiveAsProperty(specAttrNode, SLC_VALUE,
858 type, value);
859 valuesViewer.refresh();
860 formPart.markDirty();
861 } else if (specAttrNode
862 .isNodeType(SlcTypes.SLC_REF_SPEC_ATTRIBUTE)) {
863 specAttrNode.setProperty(SLC_VALUE,
864 ((Integer) value).longValue());
865 valuesViewer.refresh();
866 formPart.markDirty();
867 }
868 } catch (RepositoryException e) {
869 throw new SlcException("Cannot get celle editor", e);
870 }
871 }
872
873 }
874 }