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