Bug 458813 - Support for multi meta models in release dialog.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=458813
diff --git a/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseDialog.java b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseDialog.java
deleted file mode 100644
index 546c517..0000000
--- a/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseDialog.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2010 BMW Car IT, Technische Universitaet Muenchen, and others.
- * 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:
- * BMW Car IT - Initial API and implementation
- * Technische Universitaet Muenchen - Major refactoring and extension
- *******************************************************************************/
-package org.eclipse.emf.edapt.history.instantiation.ui;
-
-import org.eclipse.emf.edapt.common.ui.TitleMessageDialogBase;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.layout.GridData;
-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.Label;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * A dialog to support the update of package namespaces when releasing.
- *
- * @author herrmama
- * @author $Author$
- * @version $Rev$
- * @levd.rating RED Rev:
- */
-public class ReleaseDialog extends TitleMessageDialogBase {
-
-	/** Label to be replaced. */
-	private String source;
-
-	/** Widget for source label. */
-	private Text sourceText;
-
-	/** Label by which it is replaced. */
-	private String target;
-
-	/** Widget for target label. */
-	private Text targetText;
-
-	/** Widget for update of namespace URIs. */
-	private Button updateButton;
-
-	/** Whether the namespace URIs should be updated. */
-	private boolean update;
-
-	/** Constructor. */
-	public ReleaseDialog(String source) {
-		super("Update namespace URI of packages", //$NON-NLS-1$
-			"In the namespace URI of each package, a label is replaced by another one.\n" + //$NON-NLS-1$
-				"The new label will denote the release. If you want to change the namespace\n" + //$NON-NLS-1$
-				"URIs in a different, modify them manually before pressing Release."); //$NON-NLS-1$
-		this.source = source;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	protected Control createDialogArea(Composite parent) {
-		parent = (Composite) super.createDialogArea(parent);
-
-		final Composite composite = new Composite(parent, SWT.None);
-		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
-		final GridLayout layout = new GridLayout(2, false);
-		composite.setLayout(layout);
-
-		final Label sourceLabel = new Label(composite, SWT.None);
-		sourceLabel.setText("Label to match:"); //$NON-NLS-1$
-
-		sourceText = new Text(composite, SWT.BORDER);
-		sourceText.setText(source);
-		sourceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
-		final Label targetLabel = new Label(composite, SWT.None);
-		targetLabel.setText("Label to replace with:"); //$NON-NLS-1$
-
-		targetText = new Text(composite, SWT.BORDER);
-		targetText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-
-		final Label updateLabel = new Label(composite, SWT.None);
-		updateLabel.setText("Update namespace URIs:"); //$NON-NLS-1$
-
-		updateButton = new Button(composite, SWT.CHECK);
-		updateButton.setSelection(true);
-
-		return parent;
-	}
-
-	/** {@inheritDoc} */
-	@Override
-	protected void okPressed() {
-		source = sourceText.getText();
-		target = targetText.getText();
-		update = updateButton.getSelection();
-		super.okPressed();
-	}
-
-	/** Returns source lagel. */
-	public String getSource() {
-		return source;
-	}
-
-	/** Returns target label. */
-	public String getTarget() {
-		return target;
-	}
-
-	/** Returns update flag. */
-	public boolean isUpdate() {
-		return update;
-	}
-}
diff --git a/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseHandler.java b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseHandler.java
index 88d9f19..00414cb 100644
--- a/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseHandler.java
+++ b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseHandler.java
@@ -12,6 +12,7 @@
 package org.eclipse.emf.edapt.history.instantiation.ui;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import org.eclipse.emf.common.command.Command;
@@ -26,8 +27,9 @@
 import org.eclipse.emf.edapt.spi.history.History;
 import org.eclipse.emf.edapt.spi.history.Release;
 import org.eclipse.emf.edit.domain.EditingDomain;
-import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.jface.wizard.WizardDialog;
 import org.eclipse.swt.widgets.Display;
 
 /**
@@ -56,8 +58,7 @@
 			return true;
 		}
 		final boolean ignore = MessageDialog
-			.openConfirm(Display.getDefault().getActiveShell(),
-				"Metamodel inconsistent", //$NON-NLS-1$
+			.openConfirm(Display.getDefault().getActiveShell(), "Metamodel inconsistent", //$NON-NLS-1$
 				"The metamodel is inconsistent. Do you really want to release it?"); //$NON-NLS-1$
 		return ignore;
 	}
@@ -68,41 +69,24 @@
 		if (!isNsURIChanged(extent, listener.getHistory().getLastRelease())) {
 			final History history = listener.getHistory();
 			final List<EPackage> rootPackages = history.getRootPackages();
-			final String source = inferSource(rootPackages);
-			final ReleaseDialog dialog = new ReleaseDialog(source);
-			if (dialog.open() == IDialogConstants.OK_ID) {
-				final String target = dialog.getTarget();
-				if (dialog.isUpdate()) {
-					updateNamespaceURI(domain, rootPackages,
-						dialog.getSource(), target);
-					if (isNsURIChanged(extent, history.getLastRelease())) {
-						addRelease(domain, listener, target);
-					} else {
-						MessageDialog
-							.openError(Display.getDefault()
-								.getActiveShell(), "Error", //$NON-NLS-1$
-								"Namepaces URIs not fully changed since last release"); //$NON-NLS-1$
+			final ReleaseWizard releaseWizard = new ReleaseWizard(rootPackages);
+			final WizardDialog dialog = new WizardDialog(Display.getDefault().getActiveShell(), releaseWizard);
+			if (dialog.open() == Window.OK) {
+				for (final EPackage ePackage : rootPackages) {
+					if (!releaseWizard.updatePackage(ePackage)) {
+						continue;
 					}
-				} else {
-					addRelease(domain, listener, target);
+					final String source = releaseWizard.getSource(ePackage);
+					final String target = releaseWizard.getTarget(ePackage);
+					updateNamespaceURI(domain, Collections.singletonList(ePackage), source, target);
 				}
+				addRelease(domain, listener, null);
 			}
 		} else {
 			addRelease(domain, listener, null);
 		}
 	}
 
-	/** Infer the label to be replaced from the packages. */
-	private String inferSource(List<EPackage> ePackages) {
-		try {
-			final String nsURI = ePackages.get(0).getNsURI();
-			final int index = nsURI.lastIndexOf('/');
-			return nsURI.substring(index + 1);
-		} catch (final RuntimeException e) {
-			return ""; //$NON-NLS-1$
-		}
-	}
-
 	/** Update the namespace URI. */
 	private void updateNamespaceURI(EditingDomain domain,
 		List<EPackage> rootPackages, String source, String target) {
diff --git a/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseWizard.java b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseWizard.java
new file mode 100644
index 0000000..936e665
--- /dev/null
+++ b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseWizard.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (c) 2007-2015 BMW Car IT, TUM, EclipseSource Muenchen GmbH, and others.
+ *
+ * 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:
+ * Johannes Faltermeier - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.edapt.history.instantiation.ui;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.jface.wizard.Wizard;
+
+/**
+ * {@link Wizard} to update the ns uris of multiple packages.
+ *
+ * @author jfaltermeier
+ *
+ */
+public class ReleaseWizard extends Wizard {
+
+	private final Map<EPackage, ReleaseWizardPage> pages = new LinkedHashMap<EPackage, ReleaseWizardPage>();
+
+	private final Map<EPackage, Boolean> updateMap = new LinkedHashMap<EPackage, Boolean>();
+	private final Map<EPackage, String> sourceMap = new LinkedHashMap<EPackage, String>();
+	private final Map<EPackage, String> targetMap = new LinkedHashMap<EPackage, String>();
+
+	private final List<EPackage> rootPackages;
+
+	public ReleaseWizard(List<EPackage> rootPackages) {
+		if (rootPackages == null || rootPackages.isEmpty()) {
+			throw new IllegalArgumentException("There must be at least one root package."); //$NON-NLS-1$
+		}
+		this.rootPackages = rootPackages;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.jface.wizard.Wizard#getWindowTitle()
+	 */
+	@Override
+	public String getWindowTitle() {
+		return "Create Release"; //$NON-NLS-1$
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.jface.wizard.Wizard#addPages()
+	 */
+	@Override
+	public void addPages() {
+		for (final EPackage ePackage : rootPackages) {
+			final String source = inferSource(ePackage);
+			pages
+				.put(
+					ePackage,
+					new ReleaseWizardPage("Update namespace URI of package " + ePackage.getNsURI(), //$NON-NLS-1$
+						"Enter the label to replace and the target label or deselect the update button", //$NON-NLS-1$
+						null,
+						source));
+			addPage(pages.get(ePackage));
+		}
+	}
+
+	/** Infer the label to be replaced from the package. */
+	private String inferSource(EPackage ePackage) {
+		try {
+			final String nsURI = ePackage.getNsURI();
+			final int index = nsURI.lastIndexOf('/');
+			return nsURI.substring(index + 1);
+		} catch (final RuntimeException e) {
+			return ""; //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Whether the ns uri of the given EPackage should be updated.
+	 */
+	public boolean updatePackage(EPackage ePackage) {
+		if (!updateMap.containsKey(ePackage)) {
+			return false;
+		}
+		return updateMap.get(ePackage);
+	}
+
+	/**
+	 * Returns the source label to replace.
+	 */
+	public String getSource(EPackage ePackage) {
+		return sourceMap.get(ePackage);
+	}
+
+	/**
+	 * Returns the target label which replaces the source label.
+	 */
+	public String getTarget(EPackage ePackage) {
+		return targetMap.get(ePackage);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.jface.wizard.Wizard#performFinish()
+	 */
+	@Override
+	public boolean performFinish() {
+		for (final Entry<EPackage, ReleaseWizardPage> entry : pages.entrySet()) {
+			updateMap.put(entry.getKey(), entry.getValue().isUpdate());
+			if (!entry.getValue().isUpdate()) {
+				continue;
+			}
+			sourceMap.put(entry.getKey(), entry.getValue().getSource());
+			targetMap.put(entry.getKey(), entry.getValue().getTarget());
+		}
+		pages.clear();
+		return true;
+	}
+
+}
diff --git a/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseWizardPage.java b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseWizardPage.java
new file mode 100644
index 0000000..a0322d5
--- /dev/null
+++ b/plugins/org.eclipse.emf.edapt.history.editor/src/org/eclipse/emf/edapt/history/instantiation/ui/ReleaseWizardPage.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright (c) 2007-2015 BMW Car IT, TUM, EclipseSource Muenchen GmbH, and others.
+ *
+ * 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:
+ * Johannes Faltermeier - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emf.edapt.history.instantiation.ui;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * {@link WizardPage} to replace the ns uri label of a single EPackage.
+ *
+ * @author jfaltermeier
+ *
+ */
+public class ReleaseWizardPage extends WizardPage {
+
+	private final String source;
+
+	private Text sourceText;
+	private Text targetText;
+	private Button updateButton;
+
+	/**
+	 * Constructs a new {@link ReleaseWizardPage}.
+	 *
+	 * @param pageName
+	 * @param description
+	 * @param titleImage
+	 * @param source the releases label to replace
+	 */
+	protected ReleaseWizardPage(String pageName, String description, ImageDescriptor titleImage, String source) {
+		super(pageName, pageName, titleImage);
+		setDescription(description);
+		this.source = source;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	@Override
+	public void createControl(Composite parent) {
+		final Composite composite = new Composite(parent, SWT.None);
+		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+		final GridLayout layout = new GridLayout(2, false);
+		composite.setLayout(layout);
+
+		final Label sourceLabel = new Label(composite, SWT.None);
+		sourceLabel.setText("Label to match:"); //$NON-NLS-1$
+
+		sourceText = new Text(composite, SWT.BORDER);
+		sourceText.setText(source);
+		sourceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		initSourceText(sourceText);
+
+		final Label targetLabel = new Label(composite, SWT.None);
+		targetLabel.setText("Label to replace with:"); //$NON-NLS-1$
+
+		targetText = new Text(composite, SWT.BORDER);
+		targetText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+		initTargetText(targetText);
+
+		final Label updateLabel = new Label(composite, SWT.None);
+		updateLabel.setText("Update namespace URI:"); //$NON-NLS-1$
+
+		updateButton = new Button(composite, SWT.CHECK);
+		updateButton.setSelection(true);
+		initUpdateButton(updateButton);
+
+		setControl(composite);
+
+		checkIfPageComplete();
+	}
+
+	private void initSourceText(Text sourceText) {
+		sourceText.addKeyListener(new KeyAdapter() {
+			/**
+			 * {@inheritDoc}
+			 *
+			 * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
+			 */
+			@Override
+			public void keyReleased(KeyEvent e) {
+				checkIfPageComplete();
+			}
+		});
+	}
+
+	private void initTargetText(Text targetText) {
+		targetText.addKeyListener(new KeyAdapter() {
+			/**
+			 * {@inheritDoc}
+			 *
+			 * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
+			 */
+			@Override
+			public void keyReleased(KeyEvent e) {
+				checkIfPageComplete();
+			}
+		});
+	}
+
+	private void initUpdateButton(Button updateButton) {
+		updateButton.addSelectionListener(new SelectionAdapter() {
+			/**
+			 * {@inheritDoc}
+			 *
+			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+			 */
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				checkIfPageComplete();
+			}
+		});
+	}
+
+	private void checkIfPageComplete() {
+		if (!updateButton.getSelection()) {
+			setErrorMessage(null);
+			setPageComplete(true);
+			return;
+		}
+		if (sourceText.getText().isEmpty()) {
+			setErrorMessage("Label to match may not be empty"); //$NON-NLS-1$
+			setPageComplete(false);
+			return;
+		}
+		if (targetText.getText().isEmpty()) {
+			setErrorMessage("Label to replace may not be empty"); //$NON-NLS-1$
+			setPageComplete(false);
+			return;
+		}
+		if (sourceText.getText().equals(targetText.getText())) {
+			setErrorMessage("Source and target label may not be equal"); //$NON-NLS-1$
+			setPageComplete(false);
+			return;
+		}
+		setErrorMessage(null);
+		setPageComplete(true);
+	}
+
+	/** Returns source label. */
+	public String getSource() {
+		return sourceText.getText();
+	}
+
+	/** Returns target label. */
+	public String getTarget() {
+		return targetText.getText();
+	}
+
+	/** Returns update flag. */
+	public boolean isUpdate() {
+		return updateButton.getSelection();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 *
+	 * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)
+	 */
+	@Override
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible) {
+			targetText.setFocus();
+		}
+	}
+
+}