]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/wizard/MigrateWizard.java
Improved Copy Visible Data usability in time series chart editor
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / wizard / MigrateWizard.java
1 /*******************************************************************************
2  * Copyright (c) 2014, 2015 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.ui.wizard;
13
14 import java.lang.reflect.InvocationTargetException;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashSet;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.eclipse.core.runtime.IStatus;
24 import org.eclipse.core.runtime.OperationCanceledException;
25 import org.eclipse.core.runtime.Status;
26 import org.eclipse.core.runtime.SubMonitor;
27 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
28 import org.eclipse.core.runtime.preferences.InstanceScope;
29 import org.eclipse.jface.dialogs.IDialogSettings;
30 import org.eclipse.jface.dialogs.MessageDialog;
31 import org.eclipse.jface.layout.GridDataFactory;
32 import org.eclipse.jface.layout.GridLayoutFactory;
33 import org.eclipse.jface.layout.RowLayoutFactory;
34 import org.eclipse.jface.resource.ImageDescriptor;
35 import org.eclipse.jface.window.Window;
36 import org.eclipse.jface.wizard.Wizard;
37 import org.eclipse.jface.wizard.WizardPage;
38 import org.eclipse.osgi.util.NLS;
39 import org.eclipse.swt.SWT;
40 import org.eclipse.swt.custom.CCombo;
41 import org.eclipse.swt.events.ModifyEvent;
42 import org.eclipse.swt.events.ModifyListener;
43 import org.eclipse.swt.events.SelectionEvent;
44 import org.eclipse.swt.events.SelectionListener;
45 import org.eclipse.swt.graphics.Point;
46 import org.eclipse.swt.layout.GridLayout;
47 import org.eclipse.swt.widgets.Button;
48 import org.eclipse.swt.widgets.Composite;
49 import org.eclipse.swt.widgets.Control;
50 import org.eclipse.swt.widgets.Event;
51 import org.eclipse.swt.widgets.Label;
52 import org.eclipse.swt.widgets.List;
53 import org.eclipse.swt.widgets.Listener;
54 import org.eclipse.swt.widgets.Shell;
55 import org.eclipse.swt.widgets.Text;
56 import org.simantics.Simantics;
57 import org.simantics.databoard.Bindings;
58 import org.simantics.databoard.util.URIStringUtils;
59 import org.simantics.db.ReadGraph;
60 import org.simantics.db.Resource;
61 import org.simantics.db.WriteGraph;
62 import org.simantics.db.common.NamedResource;
63 import org.simantics.db.common.request.ObjectsWithType;
64 import org.simantics.db.common.request.UnaryRead;
65 import org.simantics.db.common.request.UniqueRead;
66 import org.simantics.db.common.request.WriteResultRequest;
67 import org.simantics.db.common.utils.Logger;
68 import org.simantics.db.common.utils.Versions;
69 import org.simantics.db.exception.CancelTransactionException;
70 import org.simantics.db.exception.DatabaseException;
71 import org.simantics.db.request.Read;
72 import org.simantics.diagram.stubs.DiagramResource;
73 import org.simantics.layer0.Layer0;
74 import org.simantics.modeling.MigrateModel;
75 import org.simantics.modeling.MigrateModel.MigrationOperation;
76 import org.simantics.modeling.ModelingResources;
77 import org.simantics.modeling.UserComponentMigration;
78 import org.simantics.modeling.ui.Activator;
79 import org.simantics.modeling.ui.diagramEditor.DiagramEditor;
80 import org.simantics.structural.stubs.StructuralResource2;
81 import org.simantics.ui.workbench.dialogs.ResourceSelectionDialog3;
82 import org.simantics.utils.datastructures.Pair;
83 import org.simantics.utils.datastructures.Triple;
84 import org.simantics.utils.strings.AlphanumComparator;
85 import org.simantics.utils.ui.SWTUtils;
86
87 import gnu.trove.map.hash.THashMap;
88 import gnu.trove.set.hash.THashSet;
89 import gnu.trove.set.hash.TIntHashSet;
90
91 /**
92  * @author Antti Villberg
93  */
94 public class MigrateWizard extends Wizard {
95
96         final String initial;
97         
98     MigratePage  migratePage;
99
100         IEclipsePreferences prefnode;
101     
102     public MigrateWizard(String initial) {
103         
104         this.initial = initial;
105
106         setWindowTitle(Messages.MigrateWizard_PerformMigration);
107         setNeedsProgressMonitor(true);
108         setForcePreviousAndNextButtons(false);
109         setDialogSettings(Activator.getDefault().getDialogSettings());
110
111         prefnode = InstanceScope.INSTANCE.getNode( "org.simantics.modeling.ui.wizard.MigrateWizard" ); //$NON-NLS-1$
112         
113     }
114
115     @Override
116     public void addPages() {
117         migratePage = new MigratePage(initial);
118         addPage(migratePage);
119     }
120
121     @Override
122     public boolean canFinish() {
123 //        if (model.spec.name.isEmpty())
124 //            return false;
125         return true;
126     }
127
128     @Override
129     public boolean performFinish() {
130
131         int locationIndex = migratePage.locations.getSelectionIndex();
132         if(locationIndex == -1) return true;
133
134         if(migratePage.model == null || migratePage.model.instances.isEmpty()) return true;
135
136         int[] sel = migratePage.instances.getSelectionIndices();
137         TIntHashSet sels = new TIntHashSet();
138         for(int i : sel) sels.add(i);
139
140         Collection<MigrationOperation> ops = migratePage.model.sortedShownInstances;
141         int index = 0;
142         final ArrayList<MigrationOperation> result = new ArrayList<>();
143         for(MigrationOperation op : ops) {
144                 if(sels.contains(index)) result.add(op);
145                 index++;
146         }
147         
148         if(result.isEmpty()) return true;
149         
150         try {
151             String[] report = { null };
152             getContainer().run(true, true, monitor -> {
153                 SubMonitor mon = SubMonitor.convert(monitor, 1000);
154                 try {
155                     report[0] = Simantics.getSession().syncRequest(new WriteResultRequest<String>() {
156                         @Override
157                         public String perform(WriteGraph graph) throws DatabaseException {
158                             graph.markUndoPoint();
159                             String report = UserComponentMigration.doMigration(mon.newChild(500, SubMonitor.SUPPRESS_NONE), graph, result);
160                             UserComponentMigration.doPostMigration(mon.newChild(500, SubMonitor.SUPPRESS_NONE), graph, result);
161                             mon.setTaskName(Messages.MigrateWizard_MonitorCommitingChanges);
162                             mon.subTask(""); //$NON-NLS-1$
163                             return report;
164                         }
165                     });
166
167                     // Schedule diagram reinitialization to see actual migration changes
168                     // This needs to be done because the diagram editor can't currently
169                     // refresh itself after type (InstanceOf) changes in diagram elements.
170                     Set<Resource> diagramsToReopen = Simantics.getSession().syncRequest(
171                             (Read<Set<Resource>>) graph -> componentsToDiagrams(graph, ops));
172                     SWTUtils.asyncExec(MigrateWizard.this.getContainer().getShell().getDisplay(),
173                             () -> DiagramEditor.reinitializeDiagram(diagramsToReopen));
174                 } catch (DatabaseException e) {
175                     throw new InvocationTargetException(e);
176                 } finally {
177                     monitor.done();
178                 }
179             });
180
181             ReportDialog md = new ReportDialog(getShell(), report[0], 800, 500);
182             md.open();
183
184             return true;
185         } catch (InvocationTargetException e) {
186             // Don't show user cancellations as errors.
187             Throwable cause = e.getCause();
188             if (!(cause instanceof CancelTransactionException || cause instanceof OperationCanceledException)) {
189                 Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
190                         Messages.MigrateWizard_ActivatorMigrationFailed, e.getCause()));
191             }
192         } catch (InterruptedException e) {
193             Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
194                     Messages.MigrateWizard_ActivatorMigrationInterrupted, e));
195         }
196         return false;
197     }
198
199     private static final Set<Resource> componentsToDiagrams(ReadGraph graph, Collection<MigrationOperation> ops) throws DatabaseException {
200         Layer0 L0 = Layer0.getInstance(graph);
201         ModelingResources MOD = ModelingResources.getInstance(graph);
202         Set<Resource> diagrams = new HashSet<>();
203         for (MigrationOperation op : ops) {
204             Resource composite = graph.getPossibleObject(op.instanceToMigrate.getResource(), L0.PartOf);
205             if (composite != null) {
206                 Resource diagram = graph.getPossibleObject(composite, MOD.CompositeToDiagram);
207                 if (diagram != null)
208                     diagrams.add(diagram);
209             }
210         }
211         return diagrams;
212     }
213
214     static class ReportDialog extends MessageDialog {
215         private final String report;
216         private final int initialWidth;
217         private final int initialHeight;
218
219         public ReportDialog(Shell shell, String report, int width, int height) {
220             super(shell, 
221                     Messages.MigrateWizard_MigrationReport, null, 
222                     "",  //$NON-NLS-1$
223                     MessageDialog.INFORMATION, new String[] { Messages.MigrateWizard_Continue }, 0);
224             this.report = report;
225             this.initialWidth = width;
226             this.initialHeight = height;
227         }
228
229         @Override
230         protected boolean isResizable() {
231             return true;
232         }
233
234         @Override
235         protected Point getInitialSize() {
236             return new Point(initialWidth, initialHeight);
237         }
238
239         @Override
240         protected Control createCustomArea(Composite composite) {
241             GridLayoutFactory.fillDefaults().applyTo(composite);
242             Text text = new Text(composite, SWT.MULTI | SWT.V_SCROLL | SWT.READ_ONLY | SWT.BORDER);
243             text.setText(report);
244             GridDataFactory.fillDefaults().grab(true, true).applyTo(text);
245             return composite;
246         }
247     }
248
249     abstract static class SelectionAdapter implements SelectionListener {
250         @Override
251         public void widgetDefaultSelected(SelectionEvent e) {
252             widgetSelected(e);
253         }
254     }
255
256     class MigratePage extends WizardPage {
257
258         String                initial;
259         
260         MigrateModel          model;
261
262         Text                  source;
263         Button                browseSource;
264         Text                  target;
265         Button                browseTarget;
266         Label                 symbolsLabel;
267         CCombo                symbols;
268         Label                 instanceLabel;
269         Label                             locationsLabel;
270         CCombo                locations;
271         Composite             buttonBar;
272         Label                 instancesLabel;
273         List                  instances;
274
275         /**
276          * ID of the location that has been previously selected by the user.
277          * Used to prevent the location from being reset every time the user
278          * makes a change in any of the other selections.
279          * 
280          * See first field of {@link MigrateModel#instances}.
281          */
282         String                previouslySelectedLocationId = null;
283
284         public MigratePage(String initial) {
285             super(Messages.MigrateWizard_PerformMigration, Messages.MigrateWizard_PerformMigration, null);
286             this.initial = initial;
287         }
288
289         @Override
290         public void createControl(Composite parent) {
291             Composite container = new Composite(parent, SWT.NONE);
292             {
293                 GridLayout layout = new GridLayout();
294                 layout.horizontalSpacing = 20;
295                 layout.verticalSpacing = 10;
296                 layout.numColumns = 10;
297                 container.setLayout(layout);
298             }
299
300             new Label(container, SWT.NONE).setText(Messages.MigrateWizard_SourceAnd);
301             source = new Text(container, SWT.BORDER);
302             source.setText(initial);
303             source.addModifyListener(new ModifyListener() {
304                 @Override
305                 public void modifyText(ModifyEvent e) {
306                     refreshModel();
307                     refreshInstances();
308                 }
309             });
310             GridDataFactory.fillDefaults().grab(true, false).span(8, 1).applyTo(source);
311
312             browseSource = new Button(container, SWT.NONE);
313             browseSource.setText(Messages.MigrateWizard_BrowseAnd);
314             GridDataFactory.fillDefaults().grab(false, false).applyTo(browseSource);
315             browseSource.addSelectionListener(new SelectionAdapter() {
316                 @Override
317                 public void widgetSelected(SelectionEvent e_) {
318                     try {
319                         Map<String, Pair<String, ImageDescriptor>> map = Simantics.getSession().syncRequest(new BrowseSourceContentRequest(target.getText()));
320                         String uri = queryTargetSelection(Messages.MigrateWizard_SelectSourceType, map);
321                         if (uri != null)
322                             source.setText(uri);
323                     } catch (DatabaseException e) {
324                         Logger.defaultLogError(e);
325                     }
326                 }
327             });
328
329             new Label(container, SWT.NONE).setText(Messages.MigrateWizard_TargetAnd);
330             target = new Text(container, SWT.BORDER);
331             target.setText(initial);
332             target.addModifyListener(new ModifyListener() {
333                 @Override
334                 public void modifyText(ModifyEvent e) {
335                     refreshSymbols();
336                     refreshModel();
337                     refreshInstances();
338                 }
339             });
340             GridDataFactory.fillDefaults().grab(true, false).span(8, 1).applyTo(target);
341
342             browseTarget = new Button(container, SWT.NONE);
343             browseTarget.setText(Messages.MigrateWizard_BrowseAnd1);
344             GridDataFactory.fillDefaults().grab(false, false).applyTo(browseTarget);
345             browseTarget.addSelectionListener(new SelectionAdapter() {
346                 @Override
347                 public void widgetSelected(SelectionEvent e_) {
348                     try {
349                         Map<String, Pair<String, ImageDescriptor>> map = Simantics.getSession().syncRequest(new BrowseTargetContentRequest(source.getText()));
350                         String uri = queryTargetSelection(Messages.MigrateWizard_SelectTargetType, map);
351                         if (uri != null)
352                             target.setText(uri);
353                     } catch (DatabaseException e) {
354                         Logger.defaultLogError(e);
355                     }
356                 }
357             });
358
359             symbolsLabel = new Label(container, SWT.NONE);
360             symbolsLabel.setText(Messages.MigrateWizard_TargetAndSymbol);
361             GridDataFactory.fillDefaults().applyTo(symbolsLabel);
362
363             symbols = new CCombo(container, SWT.BORDER | SWT.READ_ONLY);
364             symbols.setVisibleItemCount(10);
365             symbols.addSelectionListener(new SelectionAdapter() {
366                 @Override
367                 public void widgetSelected(SelectionEvent e) {
368                     refreshModel();
369                     refreshInstances();
370                 }
371             });
372             GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(symbols);
373
374             instanceLabel = new Label(container, SWT.NONE);
375             GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(instanceLabel);
376             instanceLabel.setText(""); //$NON-NLS-1$
377
378             locationsLabel = new Label(container, SWT.NONE);
379             locationsLabel.setText(Messages.MigrateWizard_LocationAnd);
380             locations = new CCombo(container, SWT.BORDER | SWT.READ_ONLY);
381             locations.setVisibleItemCount(25);
382             locations.addSelectionListener(new SelectionAdapter() {
383                 @Override
384                 public void widgetSelected(SelectionEvent e) {
385                     int index = locations.getSelectionIndex();
386                     if (index >= 0 && index < model.instances.size()) {
387                         previouslySelectedLocationId = model.instances.get(index).first;
388                     }
389                     refreshInstances();
390                 }
391             });
392             GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(locations);
393
394             instancesLabel = new Label(container, SWT.NONE);
395             instancesLabel.setText(Messages.MigrateWizard_SelectInstancesToMigrate);
396             GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(instancesLabel);
397
398             buttonBar = new Composite(container, SWT.NONE);
399             RowLayoutFactory.fillDefaults().type(SWT.HORIZONTAL).applyTo(buttonBar);
400             GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(buttonBar);
401             Button selectAll = new Button(buttonBar, SWT.PUSH);
402             selectAll.setText(Messages.MigrateWizard_SelectAllAnd);
403             Button selectNone = new Button(buttonBar, SWT.PUSH);
404             selectNone.setText(Messages.MigrateWizard_SelectNoneAnd);
405             selectAll.addSelectionListener(new SelectionAdapter() {
406                 @Override
407                 public void widgetSelected(SelectionEvent e) {
408                     instances.selectAll();
409                 }
410             });
411             selectNone.addSelectionListener(new SelectionAdapter() {
412                 @Override
413                 public void widgetSelected(SelectionEvent e) {
414                     instances.deselectAll();
415                 }
416             });
417
418             instances = new List(container, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
419             GridDataFactory.fillDefaults().grab(true, true).span(10, 1).applyTo(instances);
420             instances.addListener(SWT.Modify, validateListener);
421
422             refreshSymbols();
423             refreshModel();
424             refreshInstances();
425
426             setControl(container);
427             validatePage();
428         }
429
430         String queryTargetSelection(String title, Map<String, Pair<String, ImageDescriptor>> map) {
431             Shell shell = source.getShell();
432             ResourceSelectionDialog3<String> dialog = new ResourceSelectionDialog3<String>(shell, map, title, false) {
433                 @Override
434                 protected IDialogSettings getBaseDialogSettings() {
435                     return Activator.getDefault().getDialogSettings();
436                 }
437             };
438             if (dialog.open() == Window.OK)
439                 return (String) dialog.getFirstResult();
440             return null;
441         }
442
443         void refreshSymbols() {
444             try {
445
446                 final String uri = target.getText();
447
448                 Collection<NamedResource> syms = Simantics.getSession().syncRequest(new UniqueRead<Collection<NamedResource>>() {
449
450                     @Override
451                     public Collection<NamedResource> perform(ReadGraph graph) throws DatabaseException {
452
453                         Layer0 L0 = Layer0.getInstance(graph);
454                         DiagramResource DIA = DiagramResource.getInstance(graph);
455                         ModelingResources MOD = ModelingResources.getInstance(graph);
456
457                         Set<NamedResource> result = new THashSet<>();
458                         Resource componentType = graph.getResource(uri);
459
460                         Set<Resource> potentialSymbols = new THashSet<>();
461                         potentialSymbols.addAll(graph.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, DIA.ElementClass)));
462                         potentialSymbols.addAll(graph.getObjects(componentType, MOD.ComponentTypeToSymbol));
463
464                         for(Resource symbol : potentialSymbols) {
465                             if(!graph.hasStatement(symbol, MOD.SymbolToComponentType, componentType)) continue;
466                             String name = graph.getRelatedValue(symbol, L0.HasName, Bindings.STRING);
467                             if(graph.hasStatement(symbol, MOD.SymbolToComponentType, componentType))
468                                 result.add(new NamedResource(name, symbol));
469                         }
470
471                         return new ArrayList<>(result);
472
473                     }
474
475                 });
476
477                 symbols.removeAll();
478                 symbols.add(Messages.MigrateWizard_RetainSymbolName);
479                 for(NamedResource nr : syms) {
480                     symbols.add(nr.getName());
481                 }
482                 symbols.setData(syms);
483                 symbols.select(0);
484
485                 if(syms.isEmpty()) {
486                     symbolsLabel.setVisible(false);
487                     symbols.setVisible(false);
488                     GridDataFactory.fillDefaults().exclude(true).applyTo(symbolsLabel);
489                     GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(symbols);
490                 } else {
491                     symbolsLabel.setVisible(true);
492                     symbols.setVisible(true);
493                     GridDataFactory.fillDefaults().applyTo(symbolsLabel);
494                     GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(symbols);
495                 }
496
497                 symbols.getParent().layout();
498
499             } catch (DatabaseException e) {
500                 Logger.defaultLogError(e);
501             }
502         }
503
504         void refreshModel() {
505             final String sourceText = source.getText();
506             final String targetText = target.getText();
507             int symbolIndex = symbols.getSelectionIndex();
508             Resource symbol = null;
509             if(symbolIndex > 0) {
510                 @SuppressWarnings("unchecked")
511                 java.util.List<NamedResource> nrs = (java.util.List<NamedResource>)symbols.getData();
512                 symbol = nrs.get(symbolIndex-1).getResource();
513             }
514             final Resource finalSymbol = symbol;
515
516             try {
517                 model = Simantics.getSession().syncRequest(new UniqueRead<MigrateModel>() {
518                     @Override
519                     public MigrateModel perform(ReadGraph graph) throws DatabaseException {
520                         Layer0 L0 = Layer0.getInstance(graph);
521                         StructuralResource2 STR = StructuralResource2.getInstance(graph);
522
523                         Resource source = graph.getPossibleResource(sourceText);
524                         if(source == null) return model;
525                         Resource target = graph.getPossibleResource(targetText);
526                         if(target == null) return model;
527
528                         if(graph.isInstanceOf(source, STR.ComponentType)) {
529                             return UserComponentMigration.getComponentTypeModel(graph, source, target, finalSymbol);
530                         } else if(graph.isInstanceOf(source, L0.SharedOntology)) {
531                             return UserComponentMigration.getSharedOntologyModel(graph, source, target);
532                         } else {
533                             return null;
534                         }
535                     }
536                 });
537             } catch (DatabaseException e) {
538                 Logger.defaultLogError(e);
539             }
540
541             instances.removeAll();
542             locations.removeAll();
543
544             if (model == null)
545                 return;
546
547             int preSelect = -1, i = 0;
548             for (Triple<String,NamedResource,Collection<MigrationOperation>> r : model.instances) {
549                 locations.add(NLS.bind(Messages.MigrateWizard_LocationInstance, r.second.getName(), r.third.size())); 
550                 if (r.first.equals(previouslySelectedLocationId))
551                     preSelect = i;
552                 if (preSelect < 0 && model.activeModels.contains(r.second.getResource()))
553                     preSelect = i;
554                 ++i;
555             }
556             if (locations.getItemCount() == 0) {
557                 locations.add(Messages.MigrateWizard_NoInstancesFound);
558                 locations.select(0);
559             } else {
560                 locations.select(preSelect > -1 ? preSelect : 0);
561             }
562         }
563
564         void refreshInstances() {
565
566             int toMigrate = 0;
567             for (Triple<String, NamedResource, Collection<MigrationOperation>> pair : model.instances) {
568                 toMigrate += pair.third.size();
569             }
570
571             if (model.instanceCount == 0)
572                 instanceLabel.setText(Messages.MigrateWizard_NoInstancesWereFound);
573             else if (model.instanceCount == 1) {
574                 if (toMigrate == 1) {
575                     instanceLabel.setText(Messages.MigrateWizard_OneMigratableInstanceFound);
576                 } else {
577                     instanceLabel.setText(Messages.MigrateWizard_InstanceFoundCannotBeMigrated);
578                 }
579             } else {
580                 if (toMigrate < model.instanceCount) {
581                     if (toMigrate == 0) {
582                         instanceLabel
583                         .setText(NLS.bind(Messages.MigrateWizard_NumberOfInstancesFound, model.instanceCount));
584                     } else {
585                         instanceLabel.setText(NLS.bind(Messages.MigrateWizard_InstancesWereFound, model.instanceCount,
586                                 (model.instanceCount - toMigrate)));
587                     }
588                 } else {
589                     instanceLabel
590                     .setText(NLS.bind(Messages.MigrateWizard_MigratableInstancesFound, model.instanceCount));
591                 }
592             }
593
594             instances.removeAll();
595
596             if (model == null)
597                 return;
598
599             if (toMigrate == 0) {
600                 locationsLabel.setVisible(false);
601                 locations.setVisible(false);
602                 GridDataFactory.fillDefaults().exclude(true).applyTo(locationsLabel);
603                 GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(locations);
604             } else {
605                 locationsLabel.setVisible(true);
606                 locations.setVisible(true);
607                 GridDataFactory.fillDefaults().applyTo(locationsLabel);
608                 GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(locations);
609             }
610
611             if (!model.instances.isEmpty()) {
612
613                 int locationIndex = locations.getSelectionIndex();
614                 if (locationIndex == -1)
615                     return;
616
617                 model.sortedShownInstances = new ArrayList<>();
618                 for (MigrationOperation o : model.instances.get(locationIndex).third)
619                     model.sortedShownInstances.add(o);
620                 Collections.sort(model.sortedShownInstances, MIGRATION_OP_COMPARATOR);
621                 for (MigrationOperation o : model.sortedShownInstances) {
622                     String uri = o.toString();
623                     uri = uri.replace("http://Projects/Development%20Project/", ""); //$NON-NLS-1$ //$NON-NLS-2$
624                     uri = URIStringUtils.unescape(uri);
625                     instances.add(uri);
626                 }
627
628             }
629
630             if (model.sortedShownInstances.isEmpty()) {
631                 instancesLabel.setVisible(false);
632                 instances.setVisible(false);
633                 buttonBar.setVisible(false);
634                 GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(instancesLabel);
635                 GridDataFactory.fillDefaults().exclude(true).grab(true, true).span(10, 1).applyTo(instances);
636                 GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(10, 1).applyTo(buttonBar);
637             } else {
638                 GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(instancesLabel);
639                 GridDataFactory.fillDefaults().grab(true, true).span(10, 1).applyTo(instances);
640                 GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(buttonBar);
641                 instancesLabel.setVisible(true);
642                 instances.setVisible(true);
643                 buttonBar.setVisible(true);
644             }
645
646             locations.getParent().layout();
647
648         }
649
650         Listener validateListener = new Listener() {
651             @Override
652             public void handleEvent(Event event) {
653                 switch (event.type) {
654                     case SWT.Modify:
655                         validatePage();
656                     case SWT.Selection:
657                         validatePage();
658                         break;
659                     case SWT.FocusIn:
660                     {
661                         if (event.widget instanceof Text) {
662                             Text t = (Text) event.widget;
663                             t.selectAll();
664                         }
665                         break;
666                     }
667                 }
668             }
669         };
670
671         private void validatePage() {
672             setMessage(null);
673             setErrorMessage(null);
674             setPageComplete(true);
675         }
676
677     }
678
679     private static final Comparator<MigrationOperation> MIGRATION_OP_COMPARATOR = new Comparator<MigrateModel.MigrationOperation>() {
680         @Override
681         public int compare(MigrationOperation o1, MigrationOperation o2) {
682             return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1.instanceToMigrate.getName(), o2.instanceToMigrate.getName());
683         }
684     };
685
686     private static abstract class BrowseContentRequest extends UnaryRead<String, Map<String, Pair<String, ImageDescriptor>>> {
687
688         public BrowseContentRequest(String uri) {
689             super(uri);
690         }
691
692         @Override
693         public Map<String, Pair<String, ImageDescriptor>> perform(ReadGraph graph) throws DatabaseException {
694             Resource root = graph.getPossibleResource(parameter);
695             if (root == null)
696                 return null;
697
698             Map<String, Pair<String, ImageDescriptor>> result = new THashMap<>();
699             Collection<NamedResource> infos = getVersions(graph, root); 
700             for (NamedResource info : infos)
701                 result.put(graph.getURI(info.getResource()), Pair.<String,ImageDescriptor>make(Versions.getStandardPathNameString(graph, info.getResource()), null));
702
703             return result;
704         }
705
706         protected abstract Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException;
707
708     }
709
710     private static class BrowseSourceContentRequest extends BrowseContentRequest {
711         public BrowseSourceContentRequest(String uri) {
712             super(uri);
713         }
714         @Override
715         protected Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException {
716             return Versions.getOlderVersions(graph, root);
717         }
718     }
719
720     private static class BrowseTargetContentRequest extends BrowseContentRequest {
721         public BrowseTargetContentRequest(String uri) {
722             super(uri);
723         }
724         @Override
725         protected Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException {
726             return Versions.getNewerVersions(graph, root);
727         }
728     }
729
730 }