-/*******************************************************************************\r
- * Copyright (c) 2014, 2015 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * Semantum Oy - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.modeling.ui.wizard;\r
-\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.eclipse.core.runtime.IStatus;\r
-import org.eclipse.core.runtime.OperationCanceledException;\r
-import org.eclipse.core.runtime.Status;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.eclipse.core.runtime.preferences.IEclipsePreferences;\r
-import org.eclipse.core.runtime.preferences.InstanceScope;\r
-import org.eclipse.jface.dialogs.IDialogSettings;\r
-import org.eclipse.jface.dialogs.MessageDialog;\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.layout.RowLayoutFactory;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.jface.window.Window;\r
-import org.eclipse.jface.wizard.Wizard;\r
-import org.eclipse.jface.wizard.WizardPage;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.custom.CCombo;\r
-import org.eclipse.swt.events.ModifyEvent;\r
-import org.eclipse.swt.events.ModifyListener;\r
-import org.eclipse.swt.events.SelectionEvent;\r
-import org.eclipse.swt.events.SelectionListener;\r
-import org.eclipse.swt.graphics.Point;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Button;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Event;\r
-import org.eclipse.swt.widgets.Label;\r
-import org.eclipse.swt.widgets.List;\r
-import org.eclipse.swt.widgets.Listener;\r
-import org.eclipse.swt.widgets.Shell;\r
-import org.eclipse.swt.widgets.Text;\r
-import org.simantics.Simantics;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.util.URIStringUtils;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.NamedResource;\r
-import org.simantics.db.common.request.ObjectsWithType;\r
-import org.simantics.db.common.request.UnaryRead;\r
-import org.simantics.db.common.request.UniqueRead;\r
-import org.simantics.db.common.request.WriteResultRequest;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.common.utils.Versions;\r
-import org.simantics.db.exception.CancelTransactionException;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.MigrateModel;\r
-import org.simantics.modeling.MigrateModel.MigrationOperation;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.modeling.UserComponentMigration;\r
-import org.simantics.modeling.ui.Activator;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-import org.simantics.ui.workbench.dialogs.ResourceSelectionDialog3;\r
-import org.simantics.utils.datastructures.Pair;\r
-import org.simantics.utils.datastructures.Triple;\r
-import org.simantics.utils.strings.AlphanumComparator;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-/**\r
- * @author Antti Villberg\r
- */\r
-public class MigrateWizard extends Wizard {\r
-\r
- final String initial;\r
- \r
- MigratePage migratePage;\r
-\r
- IEclipsePreferences prefnode;\r
- \r
- public MigrateWizard(String initial) {\r
- \r
- this.initial = initial;\r
-\r
- setWindowTitle("Perform migration");\r
- setNeedsProgressMonitor(true);\r
- setForcePreviousAndNextButtons(false);\r
- setDialogSettings(Activator.getDefault().getDialogSettings());\r
-\r
- prefnode = InstanceScope.INSTANCE.getNode( "org.simantics.modeling.ui.wizard.MigrateWizard" );\r
- \r
- }\r
-\r
- @Override\r
- public void addPages() {\r
- migratePage = new MigratePage(initial);\r
- addPage(migratePage);\r
- }\r
-\r
- @Override\r
- public boolean canFinish() {\r
-// if (model.spec.name.isEmpty())\r
-// return false;\r
- return true;\r
- }\r
-\r
- @Override\r
- public boolean performFinish() {\r
-\r
- int locationIndex = migratePage.locations.getSelectionIndex();\r
- if(locationIndex == -1) return true;\r
-\r
- if(migratePage.model == null || migratePage.model.instances.isEmpty()) return true;\r
-\r
- int[] sel = migratePage.instances.getSelectionIndices();\r
- TIntHashSet sels = new TIntHashSet();\r
- for(int i : sel) sels.add(i);\r
-\r
- Collection<MigrationOperation> ops = migratePage.model.sortedShownInstances;\r
- int index = 0;\r
- final ArrayList<MigrationOperation> result = new ArrayList<>();\r
- for(MigrationOperation op : ops) {\r
- if(sels.contains(index)) result.add(op);\r
- index++;\r
- }\r
- \r
- if(result.isEmpty()) return true;\r
- \r
- try {\r
- String[] report = { null };\r
- getContainer().run(true, true, monitor -> {\r
- SubMonitor mon = SubMonitor.convert(monitor, 1000);\r
- try {\r
- report[0] = Simantics.getSession().syncRequest(new WriteResultRequest<String>() {\r
- @Override\r
- public String perform(WriteGraph graph) throws DatabaseException {\r
- graph.markUndoPoint();\r
- String report = UserComponentMigration.doMigration(mon.newChild(500, SubMonitor.SUPPRESS_NONE), graph, result);\r
- UserComponentMigration.doPostMigration(mon.newChild(500, SubMonitor.SUPPRESS_NONE), graph, result);\r
- mon.setTaskName("Committing Changes");\r
- mon.subTask("");\r
- return report;\r
- }\r
- });\r
- } catch (DatabaseException e) {\r
- throw new InvocationTargetException(e);\r
- } finally {\r
- monitor.done();\r
- }\r
- });\r
-\r
-\r
- ReportDialog md = new ReportDialog(getShell(), report[0], 800, 500);\r
- md.open();\r
-\r
- return true;\r
- } catch (InvocationTargetException e) {\r
- // Don't show user cancellations as errors.\r
- Throwable cause = e.getCause();\r
- if (!(cause instanceof CancelTransactionException || cause instanceof OperationCanceledException)) {\r
- Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,\r
- "Migration failed, see Error Log for details.", e.getCause()));\r
- }\r
- } catch (InterruptedException e) {\r
- Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,\r
- "Migration interrupted, see Error Log for details.", e));\r
- }\r
- return false;\r
- }\r
-\r
- static class ReportDialog extends MessageDialog {\r
- private final String report;\r
- private final int initialWidth;\r
- private final int initialHeight;\r
-\r
- public ReportDialog(Shell shell, String report, int width, int height) {\r
- super(shell, \r
- "Migration report", null, \r
- "", \r
- MessageDialog.INFORMATION, new String[] { "Continue" }, 0);\r
- this.report = report;\r
- this.initialWidth = width;\r
- this.initialHeight = height;\r
- }\r
-\r
- @Override\r
- protected boolean isResizable() {\r
- return true;\r
- }\r
-\r
- @Override\r
- protected Point getInitialSize() {\r
- return new Point(initialWidth, initialHeight);\r
- }\r
-\r
- @Override\r
- protected Control createCustomArea(Composite composite) {\r
- GridLayoutFactory.fillDefaults().applyTo(composite);\r
- Text text = new Text(composite, SWT.MULTI | SWT.V_SCROLL | SWT.READ_ONLY | SWT.BORDER);\r
- text.setText(report);\r
- GridDataFactory.fillDefaults().grab(true, true).applyTo(text);\r
- return composite;\r
- }\r
- }\r
-\r
- abstract static class SelectionAdapter implements SelectionListener {\r
- @Override\r
- public void widgetDefaultSelected(SelectionEvent e) {\r
- widgetSelected(e);\r
- }\r
- }\r
-\r
- class MigratePage extends WizardPage {\r
-\r
- String initial;\r
- \r
- MigrateModel model;\r
-\r
- Text source;\r
- Button browseSource;\r
- Text target;\r
- Button browseTarget;\r
- Label symbolsLabel;\r
- CCombo symbols;\r
- Label instanceLabel;\r
- Label locationsLabel;\r
- CCombo locations;\r
- Composite buttonBar;\r
- Label instancesLabel;\r
- List instances;\r
-\r
- /**\r
- * ID of the location that has been previously selected by the user.\r
- * Used to prevent the location from being reset every time the user\r
- * makes a change in any of the other selections.\r
- * \r
- * See first field of {@link MigrateModel#instances}.\r
- */\r
- String previouslySelectedLocationId = null;\r
-\r
- public MigratePage(String initial) {\r
- super("Perform migration", "Perform migration", null);\r
- this.initial = initial;\r
- }\r
-\r
- @Override\r
- public void createControl(Composite parent) {\r
- Composite container = new Composite(parent, SWT.NONE);\r
- {\r
- GridLayout layout = new GridLayout();\r
- layout.horizontalSpacing = 20;\r
- layout.verticalSpacing = 10;\r
- layout.numColumns = 10;\r
- container.setLayout(layout);\r
- }\r
-\r
- new Label(container, SWT.NONE).setText("&Source:");\r
- source = new Text(container, SWT.BORDER);\r
- source.setText(initial);\r
- source.addModifyListener(new ModifyListener() {\r
- @Override\r
- public void modifyText(ModifyEvent e) {\r
- refreshModel();\r
- refreshInstances();\r
- }\r
- });\r
- GridDataFactory.fillDefaults().grab(true, false).span(8, 1).applyTo(source);\r
-\r
- browseSource = new Button(container, SWT.NONE);\r
- browseSource.setText("&Browse");\r
- GridDataFactory.fillDefaults().grab(false, false).applyTo(browseSource);\r
- browseSource.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e_) {\r
- try {\r
- Map<String, Pair<String, ImageDescriptor>> map = Simantics.getSession().syncRequest(new BrowseSourceContentRequest(target.getText()));\r
- String uri = queryTargetSelection("Select Source Type", map);\r
- if (uri != null)\r
- source.setText(uri);\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- }\r
- }\r
- });\r
-\r
- new Label(container, SWT.NONE).setText("&Target:");\r
- target = new Text(container, SWT.BORDER);\r
- target.setText(initial);\r
- target.addModifyListener(new ModifyListener() {\r
- @Override\r
- public void modifyText(ModifyEvent e) {\r
- refreshSymbols();\r
- refreshModel();\r
- refreshInstances();\r
- }\r
- });\r
- GridDataFactory.fillDefaults().grab(true, false).span(8, 1).applyTo(target);\r
-\r
- browseTarget = new Button(container, SWT.NONE);\r
- browseTarget.setText("B&rowse");\r
- GridDataFactory.fillDefaults().grab(false, false).applyTo(browseTarget);\r
- browseTarget.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e_) {\r
- try {\r
- Map<String, Pair<String, ImageDescriptor>> map = Simantics.getSession().syncRequest(new BrowseTargetContentRequest(source.getText()));\r
- String uri = queryTargetSelection("Select Target Type", map);\r
- if (uri != null)\r
- target.setText(uri);\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- }\r
- }\r
- });\r
-\r
- symbolsLabel = new Label(container, SWT.NONE);\r
- symbolsLabel.setText("Target &symbol:");\r
- GridDataFactory.fillDefaults().applyTo(symbolsLabel);\r
-\r
- symbols = new CCombo(container, SWT.BORDER | SWT.READ_ONLY);\r
- symbols.setVisibleItemCount(10);\r
- symbols.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- refreshModel();\r
- refreshInstances();\r
- }\r
- });\r
- GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(symbols);\r
-\r
- instanceLabel = new Label(container, SWT.NONE);\r
- GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(instanceLabel);\r
- instanceLabel.setText("");\r
-\r
- locationsLabel = new Label(container, SWT.NONE);\r
- locationsLabel.setText("&Locations:");\r
- locations = new CCombo(container, SWT.BORDER | SWT.READ_ONLY);\r
- locations.setVisibleItemCount(25);\r
- locations.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- int index = locations.getSelectionIndex();\r
- if (index >= 0 && index < model.instances.size()) {\r
- previouslySelectedLocationId = model.instances.get(index).first;\r
- }\r
- refreshInstances();\r
- }\r
- });\r
- GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(locations);\r
-\r
- instancesLabel = new Label(container, SWT.NONE);\r
- instancesLabel.setText("&Select instances to migrate:");\r
- GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(instancesLabel);\r
-\r
- buttonBar = new Composite(container, SWT.NONE);\r
- RowLayoutFactory.fillDefaults().type(SWT.HORIZONTAL).applyTo(buttonBar);\r
- GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(buttonBar);\r
- Button selectAll = new Button(buttonBar, SWT.PUSH);\r
- selectAll.setText("Select &All");\r
- Button selectNone = new Button(buttonBar, SWT.PUSH);\r
- selectNone.setText("Select &None");\r
- selectAll.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- instances.selectAll();\r
- }\r
- });\r
- selectNone.addSelectionListener(new SelectionAdapter() {\r
- @Override\r
- public void widgetSelected(SelectionEvent e) {\r
- instances.deselectAll();\r
- }\r
- });\r
-\r
- instances = new List(container, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);\r
- GridDataFactory.fillDefaults().grab(true, true).span(10, 1).applyTo(instances);\r
- instances.addListener(SWT.Modify, validateListener);\r
-\r
- refreshSymbols();\r
- refreshModel();\r
- refreshInstances();\r
-\r
- setControl(container);\r
- validatePage();\r
- }\r
-\r
- String queryTargetSelection(String title, Map<String, Pair<String, ImageDescriptor>> map) {\r
- Shell shell = source.getShell();\r
- ResourceSelectionDialog3<String> dialog = new ResourceSelectionDialog3<String>(shell, map, title, false) {\r
- @Override\r
- protected IDialogSettings getBaseDialogSettings() {\r
- return Activator.getDefault().getDialogSettings();\r
- }\r
- };\r
- if (dialog.open() == Window.OK)\r
- return (String) dialog.getFirstResult();\r
- return null;\r
- }\r
-\r
- void refreshSymbols() {\r
- try {\r
-\r
- final String uri = target.getText();\r
-\r
- Collection<NamedResource> syms = Simantics.getSession().syncRequest(new UniqueRead<Collection<NamedResource>>() {\r
-\r
- @Override\r
- public Collection<NamedResource> perform(ReadGraph graph) throws DatabaseException {\r
-\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- DiagramResource DIA = DiagramResource.getInstance(graph);\r
- ModelingResources MOD = ModelingResources.getInstance(graph);\r
-\r
- Set<NamedResource> result = new THashSet<>();\r
- Resource componentType = graph.getResource(uri);\r
-\r
- Set<Resource> potentialSymbols = new THashSet<>();\r
- potentialSymbols.addAll(graph.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, DIA.ElementClass)));\r
- potentialSymbols.addAll(graph.getObjects(componentType, MOD.ComponentTypeToSymbol));\r
-\r
- for(Resource symbol : potentialSymbols) {\r
- if(!graph.hasStatement(symbol, MOD.SymbolToComponentType, componentType)) continue;\r
- String name = graph.getRelatedValue(symbol, L0.HasName, Bindings.STRING);\r
- if(graph.hasStatement(symbol, MOD.SymbolToComponentType, componentType))\r
- result.add(new NamedResource(name, symbol));\r
- }\r
-\r
- return new ArrayList<>(result);\r
-\r
- }\r
-\r
- });\r
-\r
- symbols.removeAll();\r
- symbols.add("<retain symbol name>");\r
- for(NamedResource nr : syms) {\r
- symbols.add(nr.getName());\r
- }\r
- symbols.setData(syms);\r
- symbols.select(0);\r
-\r
- if(syms.isEmpty()) {\r
- symbolsLabel.setVisible(false);\r
- symbols.setVisible(false);\r
- GridDataFactory.fillDefaults().exclude(true).applyTo(symbolsLabel);\r
- GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(symbols);\r
- } else {\r
- symbolsLabel.setVisible(true);\r
- symbols.setVisible(true);\r
- GridDataFactory.fillDefaults().applyTo(symbolsLabel);\r
- GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(symbols);\r
- }\r
-\r
- symbols.getParent().layout();\r
-\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- }\r
- }\r
-\r
- void refreshModel() {\r
- final String sourceText = source.getText();\r
- final String targetText = target.getText();\r
- int symbolIndex = symbols.getSelectionIndex();\r
- Resource symbol = null;\r
- if(symbolIndex > 0) {\r
- @SuppressWarnings("unchecked")\r
- java.util.List<NamedResource> nrs = (java.util.List<NamedResource>)symbols.getData();\r
- symbol = nrs.get(symbolIndex-1).getResource();\r
- }\r
- final Resource finalSymbol = symbol;\r
-\r
- try {\r
- model = Simantics.getSession().syncRequest(new UniqueRead<MigrateModel>() {\r
- @Override\r
- public MigrateModel perform(ReadGraph graph) throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
-\r
- Resource source = graph.getPossibleResource(sourceText);\r
- if(source == null) return model;\r
- Resource target = graph.getPossibleResource(targetText);\r
- if(target == null) return model;\r
-\r
- if(graph.isInstanceOf(source, STR.ComponentType)) {\r
- return UserComponentMigration.getComponentTypeModel(graph, source, target, finalSymbol);\r
- } else if(graph.isInstanceOf(source, L0.SharedOntology)) {\r
- return UserComponentMigration.getSharedOntologyModel(graph, source, target);\r
- } else {\r
- return null;\r
- }\r
- }\r
- });\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- }\r
-\r
- instances.removeAll();\r
- locations.removeAll();\r
-\r
- if (model == null)\r
- return;\r
-\r
- int preSelect = -1, i = 0;\r
- for (Triple<String,NamedResource,Collection<MigrationOperation>> r : model.instances) {\r
- locations.add(r.second.getName() + " (" + r.third.size() + " instances)");\r
- if (r.first.equals(previouslySelectedLocationId))\r
- preSelect = i;\r
- if (preSelect < 0 && model.activeModels.contains(r.second.getResource()))\r
- preSelect = i;\r
- ++i;\r
- }\r
- if (locations.getItemCount() == 0) {\r
- locations.add("<no instances were found>");\r
- locations.select(0);\r
- } else {\r
- locations.select(preSelect > -1 ? preSelect : 0);\r
- }\r
- }\r
-\r
- void refreshInstances() {\r
-\r
- int toMigrate = 0;\r
- for(Triple<String,NamedResource,Collection<MigrationOperation>> pair : model.instances) {\r
- toMigrate += pair.third.size();\r
- }\r
-\r
- if(model.instanceCount == 0)\r
- instanceLabel.setText("No instances were found.");\r
- else if(model.instanceCount == 1) {\r
- if(toMigrate == 1) {\r
- instanceLabel.setText("1 migratable instance found.");\r
- } else {\r
- instanceLabel.setText("1 instance found, but it cannot be migrated with current settings.");\r
- }\r
- } else {\r
- if(toMigrate < model.instanceCount) {\r
- if(toMigrate == 0) {\r
- instanceLabel.setText(model.instanceCount + " instances were found. None of them can be migrated with current settings.");\r
- } else {\r
- instanceLabel.setText(model.instanceCount + " instances were found. " + (model.instanceCount-toMigrate) + " of them cannot be migrated with current settings.");\r
- }\r
- } else {\r
- instanceLabel.setText(model.instanceCount + " migratable instances found. ");\r
- }\r
- }\r
-\r
- instances.removeAll();\r
-\r
- if (model == null)\r
- return;\r
-\r
- if(toMigrate == 0) {\r
- locationsLabel.setVisible(false);\r
- locations.setVisible(false);\r
- GridDataFactory.fillDefaults().exclude(true).applyTo(locationsLabel);\r
- GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(locations);\r
- } else {\r
- locationsLabel.setVisible(true);\r
- locations.setVisible(true);\r
- GridDataFactory.fillDefaults().applyTo(locationsLabel);\r
- GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(locations);\r
- }\r
-\r
- if(!model.instances.isEmpty()) {\r
-\r
- int locationIndex = locations.getSelectionIndex();\r
- if(locationIndex == -1) return;\r
-\r
- model.sortedShownInstances = new ArrayList<>();\r
- for(MigrationOperation o : model.instances.get(locationIndex).third)\r
- model.sortedShownInstances.add(o);\r
- Collections.sort(model.sortedShownInstances, MIGRATION_OP_COMPARATOR);\r
- for(MigrationOperation o : model.sortedShownInstances) {\r
- String uri = o.toString();\r
- uri = uri.replace("http://Projects/Development%20Project/", "");\r
- uri = URIStringUtils.unescape(uri);\r
- instances.add(uri);\r
- }\r
-\r
- }\r
-\r
- if(model.sortedShownInstances.isEmpty()) {\r
- instancesLabel.setVisible(false);\r
- instances.setVisible(false);\r
- buttonBar.setVisible(false);\r
- GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(instancesLabel);\r
- GridDataFactory.fillDefaults().exclude(true).grab(true, true).span(10, 1).applyTo(instances);\r
- GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(10, 1).applyTo(buttonBar);\r
- } else {\r
- GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(instancesLabel);\r
- GridDataFactory.fillDefaults().grab(true, true).span(10, 1).applyTo(instances);\r
- GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(buttonBar);\r
- instancesLabel.setVisible(true);\r
- instances.setVisible(true);\r
- buttonBar.setVisible(true);\r
- }\r
-\r
- locations.getParent().layout();\r
-\r
- }\r
-\r
- Listener validateListener = new Listener() {\r
- @Override\r
- public void handleEvent(Event event) {\r
- switch (event.type) {\r
- case SWT.Modify:\r
- validatePage();\r
- case SWT.Selection:\r
- validatePage();\r
- break;\r
- case SWT.FocusIn:\r
- {\r
- if (event.widget instanceof Text) {\r
- Text t = (Text) event.widget;\r
- t.selectAll();\r
- }\r
- break;\r
- }\r
- }\r
- }\r
- };\r
-\r
- private void validatePage() {\r
- setMessage(null);\r
- setErrorMessage(null);\r
- setPageComplete(true);\r
- }\r
-\r
- }\r
-\r
- private static final Comparator<MigrationOperation> MIGRATION_OP_COMPARATOR = new Comparator<MigrateModel.MigrationOperation>() {\r
- @Override\r
- public int compare(MigrationOperation o1, MigrationOperation o2) {\r
- return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1.instanceToMigrate.getName(), o2.instanceToMigrate.getName());\r
- }\r
- };\r
-\r
- private static abstract class BrowseContentRequest extends UnaryRead<String, Map<String, Pair<String, ImageDescriptor>>> {\r
-\r
- public BrowseContentRequest(String uri) {\r
- super(uri);\r
- }\r
-\r
- @Override\r
- public Map<String, Pair<String, ImageDescriptor>> perform(ReadGraph graph) throws DatabaseException {\r
- Resource root = graph.getPossibleResource(parameter);\r
- if (root == null)\r
- return null;\r
-\r
- Map<String, Pair<String, ImageDescriptor>> result = new THashMap<>();\r
- Collection<NamedResource> infos = getVersions(graph, root); \r
- for (NamedResource info : infos)\r
- result.put(graph.getURI(info.getResource()), Pair.<String,ImageDescriptor>make(Versions.getStandardPathNameString(graph, info.getResource()), null));\r
-\r
- return result;\r
- }\r
-\r
- protected abstract Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException;\r
-\r
- }\r
-\r
- private static class BrowseSourceContentRequest extends BrowseContentRequest {\r
- public BrowseSourceContentRequest(String uri) {\r
- super(uri);\r
- }\r
- @Override\r
- protected Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException {\r
- return Versions.getOlderVersions(graph, root);\r
- }\r
- }\r
-\r
- private static class BrowseTargetContentRequest extends BrowseContentRequest {\r
- public BrowseTargetContentRequest(String uri) {\r
- super(uri);\r
- }\r
- @Override\r
- protected Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException {\r
- return Versions.getNewerVersions(graph, root);\r
- }\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2014, 2015 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.modeling.ui.wizard;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.RowLayoutFactory;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CCombo;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.List;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.util.URIStringUtils;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.NamedResource;
+import org.simantics.db.common.request.ObjectsWithType;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.utils.Versions;
+import org.simantics.db.exception.CancelTransactionException;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.MigrateModel;
+import org.simantics.modeling.MigrateModel.MigrationOperation;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.modeling.UserComponentMigration;
+import org.simantics.modeling.ui.Activator;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.ui.workbench.dialogs.ResourceSelectionDialog3;
+import org.simantics.utils.datastructures.Pair;
+import org.simantics.utils.datastructures.Triple;
+import org.simantics.utils.strings.AlphanumComparator;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+/**
+ * @author Antti Villberg
+ */
+public class MigrateWizard extends Wizard {
+
+ final String initial;
+
+ MigratePage migratePage;
+
+ IEclipsePreferences prefnode;
+
+ public MigrateWizard(String initial) {
+
+ this.initial = initial;
+
+ setWindowTitle("Perform migration");
+ setNeedsProgressMonitor(true);
+ setForcePreviousAndNextButtons(false);
+ setDialogSettings(Activator.getDefault().getDialogSettings());
+
+ prefnode = InstanceScope.INSTANCE.getNode( "org.simantics.modeling.ui.wizard.MigrateWizard" );
+
+ }
+
+ @Override
+ public void addPages() {
+ migratePage = new MigratePage(initial);
+ addPage(migratePage);
+ }
+
+ @Override
+ public boolean canFinish() {
+// if (model.spec.name.isEmpty())
+// return false;
+ return true;
+ }
+
+ @Override
+ public boolean performFinish() {
+
+ int locationIndex = migratePage.locations.getSelectionIndex();
+ if(locationIndex == -1) return true;
+
+ if(migratePage.model == null || migratePage.model.instances.isEmpty()) return true;
+
+ int[] sel = migratePage.instances.getSelectionIndices();
+ TIntHashSet sels = new TIntHashSet();
+ for(int i : sel) sels.add(i);
+
+ Collection<MigrationOperation> ops = migratePage.model.sortedShownInstances;
+ int index = 0;
+ final ArrayList<MigrationOperation> result = new ArrayList<>();
+ for(MigrationOperation op : ops) {
+ if(sels.contains(index)) result.add(op);
+ index++;
+ }
+
+ if(result.isEmpty()) return true;
+
+ try {
+ String[] report = { null };
+ getContainer().run(true, true, monitor -> {
+ SubMonitor mon = SubMonitor.convert(monitor, 1000);
+ try {
+ report[0] = Simantics.getSession().syncRequest(new WriteResultRequest<String>() {
+ @Override
+ public String perform(WriteGraph graph) throws DatabaseException {
+ graph.markUndoPoint();
+ String report = UserComponentMigration.doMigration(mon.newChild(500, SubMonitor.SUPPRESS_NONE), graph, result);
+ UserComponentMigration.doPostMigration(mon.newChild(500, SubMonitor.SUPPRESS_NONE), graph, result);
+ mon.setTaskName("Committing Changes");
+ mon.subTask("");
+ return report;
+ }
+ });
+ } catch (DatabaseException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ });
+
+
+ ReportDialog md = new ReportDialog(getShell(), report[0], 800, 500);
+ md.open();
+
+ return true;
+ } catch (InvocationTargetException e) {
+ // Don't show user cancellations as errors.
+ Throwable cause = e.getCause();
+ if (!(cause instanceof CancelTransactionException || cause instanceof OperationCanceledException)) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ "Migration failed, see Error Log for details.", e.getCause()));
+ }
+ } catch (InterruptedException e) {
+ Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
+ "Migration interrupted, see Error Log for details.", e));
+ }
+ return false;
+ }
+
+ static class ReportDialog extends MessageDialog {
+ private final String report;
+ private final int initialWidth;
+ private final int initialHeight;
+
+ public ReportDialog(Shell shell, String report, int width, int height) {
+ super(shell,
+ "Migration report", null,
+ "",
+ MessageDialog.INFORMATION, new String[] { "Continue" }, 0);
+ this.report = report;
+ this.initialWidth = width;
+ this.initialHeight = height;
+ }
+
+ @Override
+ protected boolean isResizable() {
+ return true;
+ }
+
+ @Override
+ protected Point getInitialSize() {
+ return new Point(initialWidth, initialHeight);
+ }
+
+ @Override
+ protected Control createCustomArea(Composite composite) {
+ GridLayoutFactory.fillDefaults().applyTo(composite);
+ Text text = new Text(composite, SWT.MULTI | SWT.V_SCROLL | SWT.READ_ONLY | SWT.BORDER);
+ text.setText(report);
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(text);
+ return composite;
+ }
+ }
+
+ abstract static class SelectionAdapter implements SelectionListener {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ widgetSelected(e);
+ }
+ }
+
+ class MigratePage extends WizardPage {
+
+ String initial;
+
+ MigrateModel model;
+
+ Text source;
+ Button browseSource;
+ Text target;
+ Button browseTarget;
+ Label symbolsLabel;
+ CCombo symbols;
+ Label instanceLabel;
+ Label locationsLabel;
+ CCombo locations;
+ Composite buttonBar;
+ Label instancesLabel;
+ List instances;
+
+ /**
+ * ID of the location that has been previously selected by the user.
+ * Used to prevent the location from being reset every time the user
+ * makes a change in any of the other selections.
+ *
+ * See first field of {@link MigrateModel#instances}.
+ */
+ String previouslySelectedLocationId = null;
+
+ public MigratePage(String initial) {
+ super("Perform migration", "Perform migration", null);
+ this.initial = initial;
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ {
+ GridLayout layout = new GridLayout();
+ layout.horizontalSpacing = 20;
+ layout.verticalSpacing = 10;
+ layout.numColumns = 10;
+ container.setLayout(layout);
+ }
+
+ new Label(container, SWT.NONE).setText("&Source:");
+ source = new Text(container, SWT.BORDER);
+ source.setText(initial);
+ source.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ refreshModel();
+ refreshInstances();
+ }
+ });
+ GridDataFactory.fillDefaults().grab(true, false).span(8, 1).applyTo(source);
+
+ browseSource = new Button(container, SWT.NONE);
+ browseSource.setText("&Browse");
+ GridDataFactory.fillDefaults().grab(false, false).applyTo(browseSource);
+ browseSource.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e_) {
+ try {
+ Map<String, Pair<String, ImageDescriptor>> map = Simantics.getSession().syncRequest(new BrowseSourceContentRequest(target.getText()));
+ String uri = queryTargetSelection("Select Source Type", map);
+ if (uri != null)
+ source.setText(uri);
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
+ }
+ }
+ });
+
+ new Label(container, SWT.NONE).setText("&Target:");
+ target = new Text(container, SWT.BORDER);
+ target.setText(initial);
+ target.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ refreshSymbols();
+ refreshModel();
+ refreshInstances();
+ }
+ });
+ GridDataFactory.fillDefaults().grab(true, false).span(8, 1).applyTo(target);
+
+ browseTarget = new Button(container, SWT.NONE);
+ browseTarget.setText("B&rowse");
+ GridDataFactory.fillDefaults().grab(false, false).applyTo(browseTarget);
+ browseTarget.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e_) {
+ try {
+ Map<String, Pair<String, ImageDescriptor>> map = Simantics.getSession().syncRequest(new BrowseTargetContentRequest(source.getText()));
+ String uri = queryTargetSelection("Select Target Type", map);
+ if (uri != null)
+ target.setText(uri);
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
+ }
+ }
+ });
+
+ symbolsLabel = new Label(container, SWT.NONE);
+ symbolsLabel.setText("Target &symbol:");
+ GridDataFactory.fillDefaults().applyTo(symbolsLabel);
+
+ symbols = new CCombo(container, SWT.BORDER | SWT.READ_ONLY);
+ symbols.setVisibleItemCount(10);
+ symbols.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ refreshModel();
+ refreshInstances();
+ }
+ });
+ GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(symbols);
+
+ instanceLabel = new Label(container, SWT.NONE);
+ GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(instanceLabel);
+ instanceLabel.setText("");
+
+ locationsLabel = new Label(container, SWT.NONE);
+ locationsLabel.setText("&Locations:");
+ locations = new CCombo(container, SWT.BORDER | SWT.READ_ONLY);
+ locations.setVisibleItemCount(25);
+ locations.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ int index = locations.getSelectionIndex();
+ if (index >= 0 && index < model.instances.size()) {
+ previouslySelectedLocationId = model.instances.get(index).first;
+ }
+ refreshInstances();
+ }
+ });
+ GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(locations);
+
+ instancesLabel = new Label(container, SWT.NONE);
+ instancesLabel.setText("&Select instances to migrate:");
+ GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(instancesLabel);
+
+ buttonBar = new Composite(container, SWT.NONE);
+ RowLayoutFactory.fillDefaults().type(SWT.HORIZONTAL).applyTo(buttonBar);
+ GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(buttonBar);
+ Button selectAll = new Button(buttonBar, SWT.PUSH);
+ selectAll.setText("Select &All");
+ Button selectNone = new Button(buttonBar, SWT.PUSH);
+ selectNone.setText("Select &None");
+ selectAll.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ instances.selectAll();
+ }
+ });
+ selectNone.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ instances.deselectAll();
+ }
+ });
+
+ instances = new List(container, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+ GridDataFactory.fillDefaults().grab(true, true).span(10, 1).applyTo(instances);
+ instances.addListener(SWT.Modify, validateListener);
+
+ refreshSymbols();
+ refreshModel();
+ refreshInstances();
+
+ setControl(container);
+ validatePage();
+ }
+
+ String queryTargetSelection(String title, Map<String, Pair<String, ImageDescriptor>> map) {
+ Shell shell = source.getShell();
+ ResourceSelectionDialog3<String> dialog = new ResourceSelectionDialog3<String>(shell, map, title, false) {
+ @Override
+ protected IDialogSettings getBaseDialogSettings() {
+ return Activator.getDefault().getDialogSettings();
+ }
+ };
+ if (dialog.open() == Window.OK)
+ return (String) dialog.getFirstResult();
+ return null;
+ }
+
+ void refreshSymbols() {
+ try {
+
+ final String uri = target.getText();
+
+ Collection<NamedResource> syms = Simantics.getSession().syncRequest(new UniqueRead<Collection<NamedResource>>() {
+
+ @Override
+ public Collection<NamedResource> perform(ReadGraph graph) throws DatabaseException {
+
+ Layer0 L0 = Layer0.getInstance(graph);
+ DiagramResource DIA = DiagramResource.getInstance(graph);
+ ModelingResources MOD = ModelingResources.getInstance(graph);
+
+ Set<NamedResource> result = new THashSet<>();
+ Resource componentType = graph.getResource(uri);
+
+ Set<Resource> potentialSymbols = new THashSet<>();
+ potentialSymbols.addAll(graph.syncRequest(new ObjectsWithType(componentType, L0.ConsistsOf, DIA.ElementClass)));
+ potentialSymbols.addAll(graph.getObjects(componentType, MOD.ComponentTypeToSymbol));
+
+ for(Resource symbol : potentialSymbols) {
+ if(!graph.hasStatement(symbol, MOD.SymbolToComponentType, componentType)) continue;
+ String name = graph.getRelatedValue(symbol, L0.HasName, Bindings.STRING);
+ if(graph.hasStatement(symbol, MOD.SymbolToComponentType, componentType))
+ result.add(new NamedResource(name, symbol));
+ }
+
+ return new ArrayList<>(result);
+
+ }
+
+ });
+
+ symbols.removeAll();
+ symbols.add("<retain symbol name>");
+ for(NamedResource nr : syms) {
+ symbols.add(nr.getName());
+ }
+ symbols.setData(syms);
+ symbols.select(0);
+
+ if(syms.isEmpty()) {
+ symbolsLabel.setVisible(false);
+ symbols.setVisible(false);
+ GridDataFactory.fillDefaults().exclude(true).applyTo(symbolsLabel);
+ GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(symbols);
+ } else {
+ symbolsLabel.setVisible(true);
+ symbols.setVisible(true);
+ GridDataFactory.fillDefaults().applyTo(symbolsLabel);
+ GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(symbols);
+ }
+
+ symbols.getParent().layout();
+
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
+ }
+ }
+
+ void refreshModel() {
+ final String sourceText = source.getText();
+ final String targetText = target.getText();
+ int symbolIndex = symbols.getSelectionIndex();
+ Resource symbol = null;
+ if(symbolIndex > 0) {
+ @SuppressWarnings("unchecked")
+ java.util.List<NamedResource> nrs = (java.util.List<NamedResource>)symbols.getData();
+ symbol = nrs.get(symbolIndex-1).getResource();
+ }
+ final Resource finalSymbol = symbol;
+
+ try {
+ model = Simantics.getSession().syncRequest(new UniqueRead<MigrateModel>() {
+ @Override
+ public MigrateModel perform(ReadGraph graph) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ StructuralResource2 STR = StructuralResource2.getInstance(graph);
+
+ Resource source = graph.getPossibleResource(sourceText);
+ if(source == null) return model;
+ Resource target = graph.getPossibleResource(targetText);
+ if(target == null) return model;
+
+ if(graph.isInstanceOf(source, STR.ComponentType)) {
+ return UserComponentMigration.getComponentTypeModel(graph, source, target, finalSymbol);
+ } else if(graph.isInstanceOf(source, L0.SharedOntology)) {
+ return UserComponentMigration.getSharedOntologyModel(graph, source, target);
+ } else {
+ return null;
+ }
+ }
+ });
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
+ }
+
+ instances.removeAll();
+ locations.removeAll();
+
+ if (model == null)
+ return;
+
+ int preSelect = -1, i = 0;
+ for (Triple<String,NamedResource,Collection<MigrationOperation>> r : model.instances) {
+ locations.add(r.second.getName() + " (" + r.third.size() + " instances)");
+ if (r.first.equals(previouslySelectedLocationId))
+ preSelect = i;
+ if (preSelect < 0 && model.activeModels.contains(r.second.getResource()))
+ preSelect = i;
+ ++i;
+ }
+ if (locations.getItemCount() == 0) {
+ locations.add("<no instances were found>");
+ locations.select(0);
+ } else {
+ locations.select(preSelect > -1 ? preSelect : 0);
+ }
+ }
+
+ void refreshInstances() {
+
+ int toMigrate = 0;
+ for(Triple<String,NamedResource,Collection<MigrationOperation>> pair : model.instances) {
+ toMigrate += pair.third.size();
+ }
+
+ if(model.instanceCount == 0)
+ instanceLabel.setText("No instances were found.");
+ else if(model.instanceCount == 1) {
+ if(toMigrate == 1) {
+ instanceLabel.setText("1 migratable instance found.");
+ } else {
+ instanceLabel.setText("1 instance found, but it cannot be migrated with current settings.");
+ }
+ } else {
+ if(toMigrate < model.instanceCount) {
+ if(toMigrate == 0) {
+ instanceLabel.setText(model.instanceCount + " instances were found. None of them can be migrated with current settings.");
+ } else {
+ instanceLabel.setText(model.instanceCount + " instances were found. " + (model.instanceCount-toMigrate) + " of them cannot be migrated with current settings.");
+ }
+ } else {
+ instanceLabel.setText(model.instanceCount + " migratable instances found. ");
+ }
+ }
+
+ instances.removeAll();
+
+ if (model == null)
+ return;
+
+ if(toMigrate == 0) {
+ locationsLabel.setVisible(false);
+ locations.setVisible(false);
+ GridDataFactory.fillDefaults().exclude(true).applyTo(locationsLabel);
+ GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(locations);
+ } else {
+ locationsLabel.setVisible(true);
+ locations.setVisible(true);
+ GridDataFactory.fillDefaults().applyTo(locationsLabel);
+ GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(locations);
+ }
+
+ if(!model.instances.isEmpty()) {
+
+ int locationIndex = locations.getSelectionIndex();
+ if(locationIndex == -1) return;
+
+ model.sortedShownInstances = new ArrayList<>();
+ for(MigrationOperation o : model.instances.get(locationIndex).third)
+ model.sortedShownInstances.add(o);
+ Collections.sort(model.sortedShownInstances, MIGRATION_OP_COMPARATOR);
+ for(MigrationOperation o : model.sortedShownInstances) {
+ String uri = o.toString();
+ uri = uri.replace("http://Projects/Development%20Project/", "");
+ uri = URIStringUtils.unescape(uri);
+ instances.add(uri);
+ }
+
+ }
+
+ if(model.sortedShownInstances.isEmpty()) {
+ instancesLabel.setVisible(false);
+ instances.setVisible(false);
+ buttonBar.setVisible(false);
+ GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(9, 1).applyTo(instancesLabel);
+ GridDataFactory.fillDefaults().exclude(true).grab(true, true).span(10, 1).applyTo(instances);
+ GridDataFactory.fillDefaults().exclude(true).grab(true, false).span(10, 1).applyTo(buttonBar);
+ } else {
+ GridDataFactory.fillDefaults().grab(true, false).span(9, 1).applyTo(instancesLabel);
+ GridDataFactory.fillDefaults().grab(true, true).span(10, 1).applyTo(instances);
+ GridDataFactory.fillDefaults().grab(true, false).span(10, 1).applyTo(buttonBar);
+ instancesLabel.setVisible(true);
+ instances.setVisible(true);
+ buttonBar.setVisible(true);
+ }
+
+ locations.getParent().layout();
+
+ }
+
+ Listener validateListener = new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ switch (event.type) {
+ case SWT.Modify:
+ validatePage();
+ case SWT.Selection:
+ validatePage();
+ break;
+ case SWT.FocusIn:
+ {
+ if (event.widget instanceof Text) {
+ Text t = (Text) event.widget;
+ t.selectAll();
+ }
+ break;
+ }
+ }
+ }
+ };
+
+ private void validatePage() {
+ setMessage(null);
+ setErrorMessage(null);
+ setPageComplete(true);
+ }
+
+ }
+
+ private static final Comparator<MigrationOperation> MIGRATION_OP_COMPARATOR = new Comparator<MigrateModel.MigrationOperation>() {
+ @Override
+ public int compare(MigrationOperation o1, MigrationOperation o2) {
+ return AlphanumComparator.CASE_INSENSITIVE_COMPARATOR.compare(o1.instanceToMigrate.getName(), o2.instanceToMigrate.getName());
+ }
+ };
+
+ private static abstract class BrowseContentRequest extends UnaryRead<String, Map<String, Pair<String, ImageDescriptor>>> {
+
+ public BrowseContentRequest(String uri) {
+ super(uri);
+ }
+
+ @Override
+ public Map<String, Pair<String, ImageDescriptor>> perform(ReadGraph graph) throws DatabaseException {
+ Resource root = graph.getPossibleResource(parameter);
+ if (root == null)
+ return null;
+
+ Map<String, Pair<String, ImageDescriptor>> result = new THashMap<>();
+ Collection<NamedResource> infos = getVersions(graph, root);
+ for (NamedResource info : infos)
+ result.put(graph.getURI(info.getResource()), Pair.<String,ImageDescriptor>make(Versions.getStandardPathNameString(graph, info.getResource()), null));
+
+ return result;
+ }
+
+ protected abstract Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException;
+
+ }
+
+ private static class BrowseSourceContentRequest extends BrowseContentRequest {
+ public BrowseSourceContentRequest(String uri) {
+ super(uri);
+ }
+ @Override
+ protected Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException {
+ return Versions.getOlderVersions(graph, root);
+ }
+ }
+
+ private static class BrowseTargetContentRequest extends BrowseContentRequest {
+ public BrowseTargetContentRequest(String uri) {
+ super(uri);
+ }
+ @Override
+ protected Collection<NamedResource> getVersions(ReadGraph graph, Resource root) throws DatabaseException {
+ return Versions.getNewerVersions(graph, root);
+ }
+ }
+
+}