]> gerrit.simantics Code Review - simantics/interop.git/blob - org.simantics.interop.update/src/org/simantics/interop/update/editor/ModelUpdateEditor.java
94b24619675049ff0bf1489fd4c4fcbd4935a1eb
[simantics/interop.git] / org.simantics.interop.update / src / org / simantics / interop / update / editor / ModelUpdateEditor.java
1 package org.simantics.interop.update.editor;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Stack;
8
9 import org.eclipse.jface.resource.ImageDescriptor;
10 import org.eclipse.jface.resource.JFaceResources;
11 import org.eclipse.jface.resource.LocalResourceManager;
12 import org.eclipse.jface.viewers.CellEditor;
13 import org.eclipse.jface.viewers.CheckStateChangedEvent;
14 import org.eclipse.jface.viewers.CheckboxCellEditor;
15 import org.eclipse.jface.viewers.CheckboxTreeViewer;
16 import org.eclipse.jface.viewers.ColumnLabelProvider;
17 import org.eclipse.jface.viewers.ColumnViewer;
18 import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
19 import org.eclipse.jface.viewers.EditingSupport;
20 import org.eclipse.jface.viewers.ICheckStateListener;
21 import org.eclipse.jface.viewers.IStructuredContentProvider;
22 import org.eclipse.jface.viewers.ITreeContentProvider;
23 import org.eclipse.jface.viewers.ITreeViewerListener;
24 import org.eclipse.jface.viewers.TableViewer;
25 import org.eclipse.jface.viewers.TableViewerColumn;
26 import org.eclipse.jface.viewers.TreeExpansionEvent;
27 import org.eclipse.jface.viewers.TreeViewerColumn;
28 import org.eclipse.jface.viewers.Viewer;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.events.SelectionAdapter;
31 import org.eclipse.swt.events.SelectionEvent;
32 import org.eclipse.swt.graphics.Color;
33 import org.eclipse.swt.graphics.Image;
34 import org.eclipse.swt.graphics.RGB;
35 import org.eclipse.swt.layout.FillLayout;
36 import org.eclipse.swt.layout.GridData;
37 import org.eclipse.swt.layout.GridLayout;
38 import org.eclipse.swt.widgets.Button;
39 import org.eclipse.swt.widgets.Composite;
40 import org.eclipse.swt.widgets.Display;
41 import org.eclipse.swt.widgets.Label;
42 import org.eclipse.swt.widgets.Text;
43 import org.eclipse.ui.IEditorInput;
44 import org.simantics.db.ReadGraph;
45 import org.simantics.db.Resource;
46 import org.simantics.db.Statement;
47 import org.simantics.db.WriteGraph;
48 import org.simantics.db.common.request.WriteRequest;
49 import org.simantics.db.exception.DatabaseException;
50 import org.simantics.db.exception.DoesNotContainValueException;
51 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
52 import org.simantics.db.exception.ServiceException;
53 import org.simantics.db.layer0.util.Layer0Utils;
54 import org.simantics.db.request.Read;
55 import org.simantics.interop.test.GraphChanges;
56 import org.simantics.interop.test.GraphComparator;
57 import org.simantics.interop.update.Activator;
58 import org.simantics.interop.update.model.UpdateNode;
59 import org.simantics.interop.update.model.UpdateNode.Status;
60 import org.simantics.interop.update.model.UpdateOp;
61 import org.simantics.interop.update.model.UpdateTree;
62 import org.simantics.interop.utils.TableUtils;
63 import org.simantics.ui.workbench.ResourceEditorPart2;
64 import org.simantics.utils.datastructures.Callback;
65 import org.simantics.utils.datastructures.Pair;
66 import org.simantics.utils.ui.ExceptionUtils;
67
68
69 /**
70  * Editor for updating models.
71  * 
72  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
73  *
74  */
75 public abstract class ModelUpdateEditor extends ResourceEditorPart2 {
76
77         
78         private Composite composite;
79         private Composite errorComposite;
80         
81         private CheckboxTreeViewer changeBrowser;
82         private TableViewer changeViewer;
83         
84         private GraphChanges changes;
85         private UpdateTree updateTree;
86         
87         private Button updateAllButton;
88         private Button updateSelectedButton;
89         
90         private LocalResourceManager manager = new LocalResourceManager(JFaceResources.getResources());
91         
92         private Image checked;
93         private Image unchecked;
94         private Image warning;
95         
96         private Color containsColor;
97         private Color deletedColor;
98         private Color addedColor;
99         
100         private HashSet<Pair<Statement, Statement>> selected = new HashSet<Pair<Statement,Statement>>();
101         
102         private HashSet<UpdateNode> selectedStructure = new HashSet<UpdateNode>();
103         
104         private List<ChangeFilter> filters = new ArrayList<ChangeFilter>();
105         
106         public ModelUpdateEditor() {
107                 checked = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/tick.png"));
108                 unchecked = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/cross.png"));
109                 warning = manager.createImage(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/error.png"));
110         }
111         
112         @Override
113         public void createPartControl(Composite parent) {
114                 
115                 containsColor = new Color(parent.getDisplay(), new RGB(255,255,220));
116                 deletedColor = new Color(parent.getDisplay(), new RGB(255,220,220));
117                 addedColor = new Color(parent.getDisplay(), new RGB(220,255,220));
118                 
119                 composite = new Composite(parent, SWT.NONE);
120                 composite.setLayout(new GridLayout(1,false));
121                 
122                 errorComposite = new Composite(composite, SWT.BORDER);
123                 GridData data = new GridData();
124                 data.grabExcessHorizontalSpace = true;
125                 data.grabExcessVerticalSpace = false;
126                 data.horizontalAlignment = SWT.FILL;
127                 data.verticalAlignment = SWT.TOP;
128                 errorComposite.setLayoutData(data);
129                 errorComposite.setLayout(new GridLayout(2, false));
130                 
131                 errorComposite.setVisible(false);
132
133                 IEditorInput input = getEditorInput();
134                 if (!(input instanceof UpdateEditorInput)) {
135                         Label label = new Label(composite, SWT.NONE);
136                         label.setText("Unknown input.");
137                         return;
138                 }
139                 
140                 Composite fillComposite = new Composite(composite, SWT.NONE);
141                 data = new GridData();
142                 data.grabExcessHorizontalSpace = true;
143                 data.grabExcessVerticalSpace = true;
144                 data.horizontalAlignment = SWT.FILL;
145                 data.verticalAlignment = SWT.FILL;
146                 fillComposite.setLayoutData(data);
147                 fillComposite.setLayout(new FillLayout(SWT.VERTICAL));
148
149                 {
150                         changeBrowser = new CheckboxTreeViewer(fillComposite,SWT.MULTI|SWT.V_SCROLL|SWT.BORDER|SWT.FULL_SELECTION  );
151                         
152                         changeBrowser.setContentProvider(new UpdateTreeContentProvider());
153                         
154                         changeBrowser.getTree().setHeaderVisible(true);
155                         
156                         ColumnViewerToolTipSupport.enableFor(changeBrowser);
157
158                         
159                         TreeViewerColumn dataColumn = TableUtils.addColumn(changeBrowser, "Data", true, 600);
160
161                         dataColumn.setLabelProvider(new UpdateNodeLabelProvider());
162                         
163                         changeBrowser.addCheckStateListener(new ICheckStateListener() {
164                                 
165                                 @Override
166                                 public void checkStateChanged(CheckStateChangedEvent event) {
167                                         UpdateNode node = (UpdateNode) event.getElement();
168                                         if (node.getOp() != null) {
169                                                 node.getOp().select(Boolean.TRUE.equals(event.getChecked()));
170                                                 
171                                         }
172                                         updateSelection();
173                                         
174                                 }
175                         });
176                         changeBrowser.addTreeListener(new ITreeViewerListener() {
177                                 
178                                 @Override
179                                 public void treeExpanded(TreeExpansionEvent event) {
180                                         event.getTreeViewer().getControl().getDisplay().asyncExec(new Runnable() {
181                                                 
182                                                 @Override
183                                                 public void run() {
184                                                         updateSelection();
185                                                 }
186                                         });
187                                         
188                                 }
189                                 
190                                 @Override
191                                 public void treeCollapsed(TreeExpansionEvent event) {
192                                         
193                                 }
194                         });
195                         changeBrowser.setUseHashlookup(true);
196                         
197                 }
198                 {
199                         changeViewer = new TableViewer(fillComposite,SWT.MULTI|SWT.V_SCROLL|SWT.BORDER|SWT.FULL_SELECTION);
200                         
201                         changeViewer.getTable().setHeaderVisible(true);
202                         changeViewer.getTable().setLinesVisible(true);
203                         
204                         changeViewer.setContentProvider(new ModificationListContentProvider());
205                         
206                         changeViewer.setUseHashlookup(true);
207                         
208                         TableViewerColumn selection = TableUtils.addColumn(changeViewer, getColumntTitle(0), false, false, 20);
209                         TableViewerColumn diagram = TableUtils.addColumn(changeViewer, getColumntTitle(1), true, true, 100);
210                         TableViewerColumn symbol = TableUtils.addColumn(changeViewer, getColumntTitle(2), true, true, 100);
211                         TableViewerColumn property = TableUtils.addColumn(changeViewer, getColumntTitle(3), true, true, 100);
212                         TableViewerColumn oldValue = TableUtils.addColumn(changeViewer, getColumntTitle(4), true, true, 100);
213                         TableViewerColumn newValue = TableUtils.addColumn(changeViewer, getColumntTitle(5), true, true, 100);
214                         
215                         diagram.setLabelProvider(getLabelProvider(1));
216                         symbol.setLabelProvider(getLabelProvider(2));
217                         property.setLabelProvider(getLabelProvider(3));
218                         oldValue.setLabelProvider(getLabelProvider(4));
219                         newValue.setLabelProvider(getLabelProvider(5));
220                         
221                         selection.setLabelProvider(new SelectionLabelProvider(selected));
222                         selection.getColumn().addSelectionListener(new SelectionAdapter() {
223                                 @Override
224                                 public void widgetSelected(SelectionEvent e) {
225                                         if (changes.getModifications().size() > 0) {
226                                                 if (selected.contains(changes.getModifications().get(0))) {
227                                                         for (Pair<Statement, Statement> nr : changes.getModifications())
228                                                                 selected.remove(nr);
229                                                 } else {
230                                                         for (Pair<Statement, Statement> nr : changes.getModifications())
231                                                                 selected.add(nr);
232                                                 }
233                                                 changeViewer.refresh();
234                                         }
235                                 }
236                         });
237                         selection.setEditingSupport(new SelectionEditingSupport(changeViewer, selected));
238                 
239                 }
240                 Composite buttonComposite = new Composite(composite, SWT.NONE);
241                 
242                 data = new GridData();
243                 data.grabExcessHorizontalSpace = true;
244                 data.grabExcessVerticalSpace = false;
245                 data.horizontalAlignment = SWT.FILL;
246                 data.verticalAlignment = SWT.BOTTOM;
247                 
248                 buttonComposite.setLayoutData(data);
249                 
250                 buttonComposite.setLayout(new GridLayout(3, false));
251                 
252                 Label label = new Label(buttonComposite, SWT.NONE);
253                 data = new GridData();
254                 data.grabExcessHorizontalSpace = true;
255                 data.grabExcessVerticalSpace = false;
256                 data.horizontalAlignment = SWT.FILL;
257                 data.verticalAlignment = SWT.CENTER;
258                 label.setLayoutData(data);
259                 
260                 updateAllButton = new Button(buttonComposite, SWT.PUSH);
261                 updateAllButton.setText("Update All");
262                 updateAllButton.addSelectionListener(new SelectionAdapter() {
263                         @Override
264                         public void widgetSelected(SelectionEvent e) {
265                                 updateAll();
266                         }
267                 });
268                 updateSelectedButton = new Button(buttonComposite, SWT.PUSH);
269                 updateSelectedButton.setText("Update Selected");
270                 updateSelectedButton.addSelectionListener(new SelectionAdapter() {
271                         @Override
272                         public void widgetSelected(SelectionEvent e) {
273                                 updateSelected();
274                         }
275                 });
276
277                 load();
278                 
279         }
280         
281         protected String getColumntTitle(int i) {
282                 switch (i) {
283                 case 0:
284                         return "!";
285                 case 1:
286                         return "Diagram";
287                 case 2:
288                         return "Symbol";
289                 case 3:
290                         return "Property";
291                 case 4:
292                         return "Old Value";
293                 case 5:
294                         return "New Value";
295                 default:
296                         throw new RuntimeException("Unknown column index" + i);
297                         
298                 }
299         }
300         
301         protected abstract ColumnLabelProvider getLabelProvider(int i);
302         protected abstract Pair<GraphComparator,Boolean> getChanges(Resource r1, Resource r2)  throws DatabaseException;
303         protected abstract UpdateTree getUpdateTree(GraphChanges changes) throws DatabaseException;
304         
305         protected void addFilters(List<ChangeFilter> filters) {
306                 
307         }
308         
309         public GraphChanges getChanges() {
310                 return changes;
311         }
312         
313         private void showWarning(String text) {
314                 errorComposite.setVisible(true);
315                 
316                 Label label = new Label(errorComposite, SWT.NONE);
317                 label.setImage(warning);
318                 label = new Label(errorComposite, SWT.NONE);
319                 label.setText(text);
320                 //this.setStatusMessage("Update contains structural changes (new or deleted symbols), please create a new model.");
321                 composite.layout(true);
322         
323         }
324         
325         private void updateSelection() {
326                 Stack<UpdateNode> nodeStack = new Stack<UpdateNode>();
327                 nodeStack.push((UpdateNode)updateTree.getRootNode());
328                 while (!nodeStack.isEmpty()) {
329                         UpdateNode n = nodeStack.pop();
330                         if (n.getOp() != null) {
331                                 UpdateOp op = n.getOp();
332                                 if (!op.isAdd() && !op.isDelete()) {
333                                         changeBrowser.setGrayed(n, true);
334                                         changeBrowser.setChecked(n, true);
335                                 } else {
336                                         boolean applied = op.applied();
337                                         if (applied) {
338                                                 changeBrowser.setChecked(n, true);
339                                                 changeBrowser.setGrayed(n, true);
340                                                 selectedStructure.remove(n);
341                                         } else {
342                                                 boolean sel = op.selected();
343                                                 if (sel) {
344                                                         selectedStructure.add(n);
345                                                         
346                                                 } else {
347                                                         selectedStructure.remove(n);
348                                                 }
349                                                 changeBrowser.setChecked(n, sel);
350                                                 changeBrowser.setGrayed(n, false);
351                                         }
352                                 }
353                         } else {
354                                 changeBrowser.setGrayed(n, true);
355                                 changeBrowser.setChecked(n, true);
356                         }
357                         for (UpdateNode c : n.getChildren()) {
358                                 nodeStack.add((UpdateNode)c);
359                         }
360                 }
361                 
362                 changeBrowser.refresh();
363         }
364         
365         
366         
367         private void load() {
368                 
369                 addFilters(filters);
370
371                 UpdateEditorInput uei = (UpdateEditorInput)getEditorInput();
372                 Resource r1 = uei.getR1();
373                 Resource r2 = uei.getR2();
374                 
375
376                 try {
377                         
378                         Pair<GraphComparator,Boolean> result = getChanges(r1,r2);
379                         GraphComparator comparator  = result.first;
380                         if (result.second)
381                                 showWarning("Structural symbols have been changed. Model update is not able to update these, please create a new model.");
382                         comparator.test(getSession());
383                         changes = comparator.getChanges();
384                         changes = getSession().syncRequest(new FilterChangesRead(changes));
385                         updateTree = getUpdateTree(changes);
386                 } catch (DatabaseException e) {
387                         Text text = new Text(composite, SWT.MULTI);
388                         text.setText(e.getMessage());
389                         e.printStackTrace();
390                         return;
391                 }
392         
393
394
395                 changeViewer.setInput(changes.getModifications());
396                 changeBrowser.setInput(updateTree);
397                 updateSelection();
398         }
399         
400         
401         
402         private void updateAll() {
403                 updateAllButton.setEnabled(false);
404                 updateSelectedButton.setEnabled(false);
405                 getSession().asyncRequest(new WriteRequest(){
406                         @Override
407                         public void perform(WriteGraph graph) throws DatabaseException {
408                                 Layer0Utils.addCommentMetadata(graph, "Apply all model updates");
409                                 graph.markUndoPoint();
410                                 for (Pair<Statement, Statement> mod : changes.getModifications()) {
411                                         applyLiteralChange(graph, mod);
412                                 }
413                                 selected.clear();
414                                 changes.getModifications().clear();
415                                 
416                                 updateTree.getUpdateOps().applyAll(graph);
417                                 
418                                 Display.getDefault().asyncExec(new Runnable() {
419                                         
420                                         @Override
421                                         public void run() {
422                                                 
423                                                 updateAllButton.setEnabled(true);
424                                                 updateSelectedButton.setEnabled(true);
425                                                 updateSelection();
426                                                 changeViewer.refresh();
427                                         }
428                                 });
429                         }
430                         
431                         
432                 }, new Callback<DatabaseException>() {
433                         @Override
434                         public void run(DatabaseException parameter) {
435                                 if (parameter != null)
436                                         ExceptionUtils.logAndShowError("Cannot update model", parameter);
437                         }
438                 });
439         }
440         
441         private void applyLiteralChange(WriteGraph graph, Pair<Statement, Statement> mod) throws DoesNotContainValueException, ServiceException, ManyObjectsForFunctionalRelationException {
442                 
443                 Resource s = changes.getComparable().getLeft(mod.second.getSubject());
444                 Resource pred = mod.first.getPredicate();
445                 if (graph.hasValue(mod.second.getObject())) {
446                         Object value = graph.getValue(mod.second.getObject());
447                         graph.claimLiteral(s, pred, value);
448                 } else {
449                         graph.deny(s,pred);
450                 }
451                 
452                 
453         }
454         
455         private void updateSelected() {
456                 updateAllButton.setEnabled(false);
457                 updateSelectedButton.setEnabled(false);
458                 getSession().asyncRequest(new WriteRequest(){
459                         @Override
460                         public void perform(WriteGraph graph) throws DatabaseException {
461                                 Layer0Utils.addCommentMetadata(graph, "Apply selected model updates");
462                                 graph.markUndoPoint();
463                                 for (Pair<Statement, Statement> mod : selected) {
464                                         changes.getModifications().remove(mod);
465                                         applyLiteralChange(graph, mod);
466                                 }
467                                 selected.clear();
468                                 
469                                 updateTree.getUpdateOps().applySelected(graph);
470                                 
471                                 Display.getDefault().asyncExec(new Runnable() {
472                                         
473                                         @Override
474                                         public void run() {
475                                                 changeViewer.refresh();
476                                                 updateAllButton.setEnabled(true);
477                                                 updateSelectedButton.setEnabled(true);
478                                                 updateSelection();
479                                         }
480                                 });
481                         }
482                 });
483         }
484
485         @Override
486         public void setFocus() {
487                 composite.setFocus();
488
489         }
490         
491         /**
492          * Filters changes:
493          * 1. Changes that are not essential for model update (changes that can be found when the models are axcatly the same)
494          * 2. Runs custom filters for value changes. 
495          * 
496          * @param g
497          * @param changes
498          * @return
499          * @throws DatabaseException
500          */
501         protected GraphChanges filterChanges(ReadGraph g, GraphChanges changes) throws DatabaseException 
502     {
503                 
504                 List<Pair<Statement,Statement>> modifications = new ArrayList<Pair<Statement,Statement>>();
505                 
506         for (Pair<Statement, Statement> mod : changes.getModifications()) {
507                 
508                 boolean accept = true;
509                 for (ChangeFilter filter : filters) {
510                         if (!filter.accept(g, mod)) {
511                                 accept = false;
512                                 break;
513                         }       
514                 }
515                 if (accept)
516                         modifications.add(mod);
517         }
518         GraphChanges newChanges =  new GraphChanges(changes.getResource1(),changes.getResource2(),changes.getDeletions(), changes.getAdditions(), modifications, changes.getComparable());
519         return newChanges;
520     }
521         
522         public interface ChangeFilter {
523                 public boolean accept(ReadGraph g, Pair<Statement, Statement> change) throws DatabaseException;
524         }
525         
526         
527         
528         
529         /**
530          * 
531          * Filters floating point value changes (default filter is set filter when the change is less than 1%)  
532          *
533          */
534         protected class FPValueFilter implements ChangeFilter  {
535                 
536                 private double percentage = 0.01;
537                 
538                 public FPValueFilter() {
539                         
540                 }
541                 
542                 public FPValueFilter(double percentage) {
543                         if (percentage < 0.0 || percentage > 1.0)
544                                 throw new IllegalArgumentException("Percentage must be between 0.0 and 1.0.");
545                         this.percentage = percentage;
546                 }
547                 
548                 @Override
549                 public boolean accept(ReadGraph g, Pair<Statement, Statement> change) throws DatabaseException {
550                         //filter floating point values that have less than 1% difference.
551                         if (!g.hasValue(change.first.getObject()) || !g.hasValue(change.second.getObject()))
552                                 return true;
553                 Object v1 = g.getValue(change.first.getObject());
554                 Object v2 = g.getValue(change.second.getObject());
555                 
556                 if (v1 instanceof Double && v2 instanceof Double) {
557                         double d1 = (Double)v1;
558                         double d2 = (Double)v2;
559                         if (Math.abs(d1-d2) / Math.max(Math.abs(d1), Math.abs(d2)) < percentage)
560                                 return false;
561                 } else if (v1 instanceof Float && v2 instanceof Float) {
562                         float d1 = (Float)v1;
563                         float d2 = (Float)v2;
564                         if (Math.abs(d1-d2) / Math.max(Math.abs(d1), Math.abs(d2)) < percentage)
565                                 return false;
566                 }
567
568                 return true;
569                 }
570         }
571
572         
573         private class FilterChangesRead implements Read<GraphChanges> {
574                 private GraphChanges changes;
575                 public FilterChangesRead(GraphChanges changes) {
576                         this.changes = changes;
577                 }
578                 
579                 @Override
580                 public GraphChanges perform(ReadGraph graph) throws DatabaseException {
581                         return filterChanges(graph, changes);
582                 }
583         }
584         
585         
586         private class ModificationListContentProvider implements IStructuredContentProvider {
587                 
588                 @SuppressWarnings("unchecked")
589                 @Override
590                 public Object[] getElements(Object inputElement) {
591                         if (inputElement == null)
592                                 return null;
593                         Collection<Pair<Statement, Statement>> coll = (Collection<Pair<Statement, Statement>>)inputElement;
594                         return coll.toArray();
595                 }
596                 
597                 @Override
598                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
599                         
600                 }
601                 
602                 @Override
603                 public void dispose() {
604                         
605                 }
606         }
607         
608         private class UpdateTreeContentProvider implements ITreeContentProvider {
609                 @Override
610                 public Object[] getElements(Object inputElement) {
611                         if (inputElement instanceof UpdateTree)
612                                 return new Object[]{((UpdateTree)inputElement).getRootNode()};
613                         if (inputElement instanceof UpdateNode) {
614                                 UpdateNode node = (UpdateNode)inputElement;
615                                 return node.getChildren().toArray();
616                         }
617                         return new Object[0];
618                 }
619                 
620                 @Override
621                 public Object getParent(Object element) {
622                         return null;
623                 }
624                 
625                 @Override
626                 public Object[] getChildren(Object parentElement) {
627                         UpdateNode node = (UpdateNode)parentElement;
628                         return node.getChildren().toArray();
629                 }
630                 
631                 @Override
632                 public boolean hasChildren(Object element) {
633                         UpdateNode node = (UpdateNode)element;
634                         return node.getChildren().size() > 0;
635                 }
636                 
637                 @Override
638                 public void dispose() {
639                         
640                 }
641                 
642                 @Override
643                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
644                         
645                 }
646         }
647         
648         private class SelectionLabelProvider extends ColumnLabelProvider {
649                 
650                 Collection<?>  selected;
651                 public SelectionLabelProvider(Collection<?>  selected) {
652                         this.selected = selected;
653                 }
654                 @Override
655                 public String getText(Object element) {
656                         return "";
657                 }
658                 
659                 @Override
660                 public Image getImage(Object element) {
661                         if (selected.contains(element))
662                                 return checked;
663                         else
664                                 return unchecked;
665                 }
666         }
667         
668         private class UpdateNodeLabelProvider extends ColumnLabelProvider {
669                 
670                 @Override
671                 public String getText(Object element) {
672                         final UpdateNode node = (UpdateNode)element;
673                         try  {
674                                 return getSession().syncRequest(new Read<String>() {
675                                         @Override
676                                         public String perform(ReadGraph graph) throws DatabaseException {
677                                                 return node.getLabel(graph);
678                                         }
679                                 });
680                         } catch (Exception e) {
681                                 return e.getMessage();
682                         }
683                 }
684                 
685                 @Override
686                 public Image getImage(Object element) {
687                         final UpdateNode node = (UpdateNode)element;
688                         try  {
689                                 ImageDescriptor id = getSession().syncRequest(new Read<ImageDescriptor>() {
690                                         @Override
691                                         public ImageDescriptor perform(ReadGraph graph) throws DatabaseException {
692                                                 return node.getImage(graph);
693                                         }
694                                 });
695                                 return manager.createImage(id);
696                         } catch (Exception e) {
697                                 return null;
698                         }
699                 }
700                 
701                 @Override
702                 public String getToolTipText(Object element) {
703                         final UpdateNode node = (UpdateNode)element;
704                         if (node.getOp() != null) {
705                                 return node.getOp().toString();
706                         } else {
707                                 return null;
708                         }
709                 }
710                 
711                 @Override
712                 public int getToolTipDisplayDelayTime(Object object) {
713                         return 1000;
714                 }
715                 
716                 @Override
717                 public int getToolTipTimeDisplayed(Object object) {
718                         return 10000;
719                 }
720
721                 @Override
722                 public Color getBackground(Object element) {
723                         final UpdateNode node = (UpdateNode)element;
724                         Status status = node.getStatus();
725                         if (status == Status.CONTAINS)
726                                 return containsColor;
727                         if (status == Status.DELETED)
728                                 return deletedColor;
729                         if (status == Status.NEW)
730                                 return addedColor;
731                         return null;            
732                 }
733         }
734         
735         private class SelectionEditingSupport extends EditingSupport {
736                 
737                 @SuppressWarnings("rawtypes")
738                 Collection selected;
739
740                 
741                 @SuppressWarnings("rawtypes")
742                 public SelectionEditingSupport(ColumnViewer viewer, Collection selected) {
743                         super(viewer);
744                         this.selected = selected;
745                         
746                 }
747
748                 @Override
749                 protected boolean canEdit(Object element) {
750                         return true;
751                 }
752                 
753                 @Override
754                 protected CellEditor getCellEditor(Object element) {
755                         return new CheckboxCellEditor(null, SWT.CHECK);
756                 }
757                 
758                 @Override
759                 protected Object getValue(Object element) {
760                         return selected.contains(element);
761                 }
762                 
763                 @SuppressWarnings("unchecked")
764                 @Override
765                 protected void setValue(Object element, Object value) {
766                         if (Boolean.TRUE.equals(value))
767                                 selected.add(element);
768                         else
769                                 selected.remove(element);
770                         
771                         getViewer().refresh(element);
772                 }
773                 
774                 
775         }
776
777
778 }