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