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