Bug 432892: Application does not work after renaming the project

Renaming a project and renaming a referenced project is now supported.
"platform:/plugin" and "bundleclass://" uris are processed in plugin.xml

I have refactored the code to be more clear.

the product file is not touched yet.

Change-Id: Ib407ab705134ff6f7a51f6843138fda55ebc3e96
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=432892
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.tools.emf.editor3x/META-INF/MANIFEST.MF
index 56445da..c5ec6f4 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/META-INF/MANIFEST.MF
@@ -30,7 +30,8 @@
  org.eclipse.ltk.core.refactoring;bundle-version="3.5.200",
  org.eclipse.search;bundle-version="3.7.0",
  org.eclipse.text;bundle-version="3.5.100",
- org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0"
+ org.eclipse.e4.ui.model.workbench;bundle-version="1.0.0",
+ org.eclipse.pde.ui
 Service-Component: OSGI-INF/pdecontributionprovider.xml, OSGI-INF/xmiresourcecontextfunction.xml, OSGI-INF/projectfunction.xml, OSGI-INF/pdee4xmiprovider.xml, OSGI-INF/pdeextensionlookup.xml, OSGI-INF/modelextractor.xml 
 Bundle-ActivationPolicy: lazy
 Bundle-Vendor: %Bundle-Vendor
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/plugin.xml b/bundles/org.eclipse.e4.tools.emf.editor3x/plugin.xml
index 0d40419..d4c0345 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/plugin.xml
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/plugin.xml
@@ -64,6 +64,9 @@
             <instanceof
                   value="org.eclipse.core.resources.IFolder">
             </instanceof>
+            <instanceof
+                  value="org.eclipse.core.resources.IProject">
+            </instanceof>
          </or>
 	  	  </with>
 	  	</enablement>
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelMoveParticipant.java b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelMoveParticipant.java
index 2ec2342..10d825f 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelMoveParticipant.java
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelMoveParticipant.java
@@ -1,3 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Remain Software, Industrial-TSI 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:
+ *     Wim Jongman <wim.jongman@remainsoftware.com> - Bug 395174: e4xmi should participate in package renaming 
+ *                                                    Bug 432892: Eclipse 4 Application does not work after renaming the project name
+ ******************************************************************************/
 package org.eclipse.e4.tools.emf.editor3x;
 
 import org.eclipse.core.resources.IFile;
@@ -16,33 +27,31 @@
 import org.eclipse.ltk.core.refactoring.participants.MoveParticipant;
 
 public class ModelMoveParticipant extends MoveParticipant {
-	private IType _type;
-	private IPackageFragment _pckage;
-	private IFile _file;
-	private IFolder _folder;
+	private IType fType;
+	private IPackageFragment fPckage;
+	private IFile fFile;
+	private RefactorModel fModel;
 
 	@Override
-	protected boolean initialize(Object element) {
+	protected boolean initialize(Object pElement) {
 
-		if (element instanceof IType) {
-			_type = (IType) element;
+		fModel = RefactorModel.getModel(this);
+
+		if (pElement instanceof IType) {
+			fType = (IType) pElement;
 			return true;
 		}
 
-		if (element instanceof IPackageFragment) {
-			_pckage = (IPackageFragment) element;
+		if (pElement instanceof IPackageFragment) {
+			fPckage = (IPackageFragment) pElement;
 			return true;
 		}
 
-		if (element instanceof IFile) {
-			_file = (IFile) element;
+		if (pElement instanceof IFile) {
+			fFile = (IFile) pElement;
 			return true;
 		}
 
-		if (element instanceof IFolder) {
-			_folder = (IFolder) element;
-			return true;
-		}
 		return false;
 	}
 
@@ -52,42 +61,37 @@
 	}
 
 	@Override
-	public RefactoringStatus checkConditions(IProgressMonitor pm,
-			CheckConditionsContext context) throws OperationCanceledException {
+	public RefactoringStatus checkConditions(IProgressMonitor pMonitor,
+			CheckConditionsContext pContext) throws OperationCanceledException {
 		return new RefactoringStatus();
 	}
 
 	@Override
-	public Change createChange(IProgressMonitor pm) throws CoreException,
+	public Change createChange(IProgressMonitor pMonitor) throws CoreException,
 			OperationCanceledException {
 
-		pm.beginTask("Creating Change ..", IProgressMonitor.UNKNOWN);
+		pMonitor.beginTask("Creating Change ..", IProgressMonitor.UNKNOWN);
 
 		Change change = null;
 
-		if (_type != null) {
-			change = createClassChange(pm, _type);
+		if (fType != null) {
+			change = createClassChange(pMonitor, fType);
 		}
 
-		else if (_pckage != null) {
-			change = createPackageChange(pm, _pckage);
+		else if (fPckage != null) {
+			change = createPackageChange(pMonitor, fPckage);
 		}
 
-		else if (_file != null) {
-			change = createFileChange(pm, _file);
+		else if (fFile != null) {
+			change = createFileChange(pMonitor, fFile);
 		}
 
-		//
-		// if (_folder != null) {
-		// return createFolderChange(pm, _folder);
-		// }
-
-		pm.done();
+		pMonitor.done();
 
 		return change;
 	}
 
-	private Change createFileChange(IProgressMonitor pm, IFile file)
+	private Change createFileChange(IProgressMonitor pMonitor, IFile file)
 			throws CoreException {
 
 		String newUrl = "platform:/plugin/";
@@ -104,14 +108,15 @@
 
 		String oldUrl = "platform:/plugin" + file.getFullPath();
 
-		return RefactorParticipantDelegate.createChange(pm, this, oldUrl,
-				newUrl);
+		fModel.addTextRename(oldUrl, newUrl);
+
+		return RefactorParticipantDelegate.createChange(pMonitor, fModel);
 	}
 
-	private Change createPackageChange(IProgressMonitor pm,
-			IPackageFragment pckage) throws CoreException,
+	private Change createPackageChange(IProgressMonitor pMonitor,
+			IPackageFragment pPckage) throws CoreException,
 			OperationCanceledException {
-		String fromBundle = Util.getBundleSymbolicName(pckage.getJavaProject()
+		String fromBundle = Util.getBundleSymbolicName(pPckage.getJavaProject()
 				.getProject());
 
 		IPackageFragmentRoot fragmentRoot = (IPackageFragmentRoot) getArguments()
@@ -120,32 +125,35 @@
 				.getJavaProject().getProject());
 
 		final String newUrl = "bundleclass://" + toBundle + "/"
-				+ pckage.getElementName();
+				+ pPckage.getElementName();
 
 		String oldUrl = "bundleclass://" + fromBundle + "/"
-				+ pckage.getElementName();
+				+ pPckage.getElementName();
 
-		return RefactorParticipantDelegate.createChange(pm, this, oldUrl,
-				newUrl);
+		fModel.addTextRename(oldUrl, newUrl);
+
+		return RefactorParticipantDelegate.createChange(pMonitor, fModel);
 	}
 
-	private Change createClassChange(IProgressMonitor pm, IType type)
+	private Change createClassChange(IProgressMonitor pMonitor, IType pType)
 			throws CoreException, OperationCanceledException {
-		String fromBundle = Util.getBundleSymbolicName(_type.getJavaProject()
+		String fromBundle = Util.getBundleSymbolicName(fType.getJavaProject()
 				.getProject());
-		String fromClassname = type.getFullyQualifiedName();
+		String fromClassname = pType.getFullyQualifiedName();
 
 		IPackageFragment fragment = (IPackageFragment) getArguments()
 				.getDestination();
 		String toBundle = Util.getBundleSymbolicName(fragment.getJavaProject()
 				.getProject());
-		String toClassName = fragment.getElementName().length() == 0 ? type
+		String toClassName = fragment.getElementName().length() == 0 ? pType
 				.getElementName() : fragment.getElementName() + "."
-				+ type.getElementName();
+				+ pType.getElementName();
 
-		return RefactorParticipantDelegate.createChange(pm, this,
-				"bundleclass://" + fromBundle + "/" + fromClassname,
-				"bundleclass://" + toBundle + "/" + toClassName);
+		return RefactorParticipantDelegate.createChange(
+				pMonitor,
+				fModel.addTextRename("bundleclass://" + fromBundle + "/"
+						+ fromClassname, "bundleclass://" + toBundle + "/"
+						+ toClassName));
 	}
 
 }
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelRenameParticipant.java b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelRenameParticipant.java
index 24ee9ce..439e913 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelRenameParticipant.java
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/ModelRenameParticipant.java
@@ -7,11 +7,15 @@
  *
  * Contributors:
  *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ *     Wim Jongman <wim.jongman@remainsoftware.com> - Bug 395174: e4xmi should participate in package renaming 
+ *                                                    Bug 432892: Eclipse 4 Application does not work after renaming the project name
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.editor3x;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
@@ -24,33 +28,41 @@
 
 public class ModelRenameParticipant extends
 		org.eclipse.ltk.core.refactoring.participants.RenameParticipant {
-	private IType _type;
-	private IPackageFragment _pckage;
-	private IFile _file;
-	private IFolder _folder;
+	private IType fType;
+	private IPackageFragment fPckage;
+	private IFile fFile;
+	private IFolder fFolder;
+	private IProject fProject;
+	private RefactorModel fModel;
 
 	@Override
 	protected boolean initialize(Object element) {
 
 		if (element instanceof IType) {
-			_type = (IType) element;
+			fType = (IType) element;
 			return true;
 		}
 
 		if (element instanceof IPackageFragment) {
-			_pckage = (IPackageFragment) element;
+			fPckage = (IPackageFragment) element;
 			return true;
 		}
 
 		if (element instanceof IFile) {
-			_file = (IFile) element;
+			fFile = (IFile) element;
 			return true;
 		}
 
 		if (element instanceof IFolder) {
-			_folder = (IFolder) element;
+			fFolder = (IFolder) element;
 			return true;
 		}
+
+		if (element instanceof IProject) {
+			fProject = (IProject) element;
+			return true;
+		}
+
 		return false;
 	}
 
@@ -68,25 +80,50 @@
 	@Override
 	public Change createChange(IProgressMonitor pm) throws CoreException,
 			OperationCanceledException {
-		if (_type != null) {
-			return createClassChange(pm, _type);
+
+		fModel = RefactorModel.getModel(this);
+
+		if (fType != null) {
+			return createClassChange(pm, fType);
 		}
 
-		if (_pckage != null) {
-			return createPackageChange(pm, _pckage);
+		if (fPckage != null) {
+			return createPackageChange(pm, fPckage);
 		}
 
-		if (_file != null) {
-			return createFileChange(pm, _file);
+		if (fFile != null) {
+			return createFileChange(pm, fFile);
 		}
 
-		if (_folder != null) {
-			return createFolderChange(pm, _folder);
+		if (fFolder != null) {
+			return createFolderChange(pm, fFolder);
+		}
+
+		if (fProject != null) {
+			return createProjectChange(pm, fProject);
 		}
 
 		return null;
 	}
 
+	private Change createProjectChange(IProgressMonitor pm, IProject project)
+			throws CoreException {
+
+		if (!getArguments().getUpdateReferences())
+			return null;
+
+		fModel.addTextRename("platform:/plugin/" + project.getName() + "/",
+				"platform:/plugin/" + getArguments().getNewName() + "/");
+		fModel.addTextRename("bundleclass://" + project.getName() + "/",
+				"bundleclass://" + getArguments().getNewName() + "/");
+
+		fModel.setProjectRename(project, ((IWorkspaceRoot) project.getParent())
+				.getProject(getArguments().getNewName()));
+
+		return RefactorParticipantDelegate.createChange(pm, fModel);
+
+	}
+
 	private Change createFolderChange(IProgressMonitor pm, IFolder folder)
 			throws CoreException {
 
@@ -95,14 +132,15 @@
 			SPLIT = "";
 		}
 
-		String newUrl = "platform:/plugin/" + folder.getProject().getName() + "/"
-				+ folder.getParent().getProjectRelativePath().toString()
+		String newUrl = "platform:/plugin/" + folder.getProject().getName()
+				+ "/" + folder.getParent().getProjectRelativePath().toString()
 				+ SPLIT + getArguments().getNewName();
 
 		String oldUrl = "platform:/plugin" + folder.getFullPath();
 
-		return RefactorParticipantDelegate.createChange(pm, this, oldUrl,
-				newUrl);
+		fModel.addTextRename(oldUrl, newUrl);
+
+		return RefactorParticipantDelegate.createChange(pm, fModel);
 	}
 
 	private Change createFileChange(IProgressMonitor pm, IFile file)
@@ -115,11 +153,10 @@
 		String newUrl = "platform:/plugin/" + file.getProject().getName() + "/"
 				+ file.getParent().getProjectRelativePath().toString() + SPLIT
 				+ getArguments().getNewName();
-
 		String oldUrl = "platform:/plugin" + file.getFullPath();
+		fModel.addTextRename(oldUrl, newUrl);
 
-		return RefactorParticipantDelegate.createChange(pm, this, oldUrl,
-				newUrl);
+		return RefactorParticipantDelegate.createChange(pm, fModel);
 	}
 
 	private Change createPackageChange(IProgressMonitor pm,
@@ -132,9 +169,9 @@
 
 		String oldUrl = "bundleclass://" + bundle + "/"
 				+ pckage.getElementName();
+		fModel.addTextRename(oldUrl, newUrl);
 
-		return RefactorParticipantDelegate.createChange(pm, this, oldUrl,
-				newUrl);
+		return RefactorParticipantDelegate.createChange(pm, fModel);
 	}
 
 	private Change createClassChange(IProgressMonitor pm, IType type)
@@ -150,9 +187,9 @@
 						.getElementName() + "." + getArguments().getNewName());
 		String oldUrl = "bundleclass://" + bundle + "/"
 				+ type.getFullyQualifiedName().replace(".", "\\.");
+		fModel.addTextRename(oldUrl, newUrl);
 
-		return RefactorParticipantDelegate.createChange(pm, this, oldUrl,
-				newUrl);
+		return RefactorParticipantDelegate.createChange(pm, fModel);
 	}
 
 }
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorModel.java b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorModel.java
new file mode 100644
index 0000000..58d71e2
--- /dev/null
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorModel.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * Copyright (c) 2014 Remain Software, Industrial-TSI 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:
+ *     Wim Jongman <wim.jongman@remainsoftware.com> - Bug 432892: Eclipse 4 Application does not work after renaming the project name
+ ******************************************************************************/
+package org.eclipse.e4.tools.emf.editor3x;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.ltk.core.refactoring.TextChange;
+import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
+
+/**
+ * A temporary data storage for Ecipse 4 model refactoring. Use the static
+ * methods to get hold of an instance.
+ * 
+ * @author Remain Software - Wim Jongman
+ *
+ */
+public class RefactorModel {
+
+	int fIndex = 0;
+	IProject fNewProject;
+	List<String> fNewTexts = new ArrayList<String>();
+
+	IProject fOldProject;
+
+	List<String> fOldTexts = new ArrayList<String>();
+
+	private RefactoringParticipant fParticipant;
+
+	/**
+	 * Factory for an empty model. Use the
+	 * {@link #addTextRename(String, String)} method to add one or more text
+	 * renames.
+	 * 
+	 * @param pParticipant
+	 * @return the model
+	 */
+	public static RefactorModel getModel(RefactoringParticipant pParticipant) {
+		return new RefactorModel().setRefactorParticipant(pParticipant);
+	}
+
+	/**
+	 * Factory for a model with one rename. Use the
+	 * {@link #addTextRename(String, String)} method to add one or more text
+	 * renames.
+	 * 
+	 * @param pParticipant
+	 * @param pOldText
+	 * @param pNewText
+	 * @return the model.
+	 */
+	public static RefactorModel getModel(RefactoringParticipant pParticipant,
+			String pOldText, String pNewText) {
+		return new RefactorModel().addTextRename(pOldText, pNewText);
+	}
+
+	/**
+	 * Factory for a model with one rename and a project rename. The project
+	 * rename uses the old and new project because the refactoring framework
+	 * expects the already renamed filenames. Use the
+	 * {@link #addTextRename(String, String)} method to add one or more text
+	 * renames and the old and the new project.
+	 * 
+	 * @param pParticipant
+	 * @param pOldText
+	 * @param pNewText
+	 * @param pOldProject
+	 * @param pNewProject
+	 * @return the model.
+	 */
+	public static RefactorModel getModel(RefactoringParticipant pParticipant,
+			String pOldText, String pNewText, IProject pOldProject,
+			IProject pNewProject) {
+		return new RefactorModel().addTextRename(pOldText, pNewText)
+				.setProjectRename(pOldProject, pNewProject)
+				.setRefactorParticipant(pParticipant);
+	}
+
+	/**
+	 * Adds a text rename to be processed later. For example, if the project
+	 * name changes there can be <code>bundlclass://</code> and
+	 * <code>platform:/plugin</code> changes.
+	 * 
+	 * @param oldText
+	 * @param newText
+	 * @return the model
+	 */
+	public RefactorModel addTextRename(String oldText, String newText) {
+		Assert.isNotNull(oldText);
+		Assert.isNotNull(newText);
+		fOldTexts.add(oldText);
+		fNewTexts.add(newText);
+		return this;
+	}
+
+	/**
+	 * When project renaming this returns the new project. This project does not
+	 * necessarily exist yet.
+	 * 
+	 * @return the new project or null if it was not set
+	 * @see RefactorModel#setProjectRename(IProject, IProject)
+	 */
+	public IProject getNewProject() {
+		return fNewProject;
+	}
+
+	/**
+	 * @return the current index set by {@link #setIndex(int)}
+	 */
+	public String getNewTextCurrentIndex() {
+		return fNewTexts.get(fIndex);
+	}
+
+	/**
+	 * When project renaming this returns the old project.
+	 * 
+	 * @return the new project or null if it was not set
+	 * @see RefactorModel#setProjectRename(IProject, IProject)
+	 */
+	public IProject getOldProject() {
+		return fOldProject;
+	}
+
+	/**
+	 * 
+	 * @return the old text in the current index.
+	 */
+	public String getOldTextCurrentIndex() {
+		return fOldTexts.get(fIndex);
+	}
+
+	/**
+	 * @return
+	 */
+	public RefactoringParticipant getRefactoringParticipant() {
+		return fParticipant;
+	}
+
+	/**
+	 * @return the number of text renames in this model
+	 */
+	public int getRenameCount() {
+		return fOldTexts.size();
+	}
+
+	/**
+	 * Delegates to the same method of the embedded RefactoringParticipant.
+	 * 
+	 * @param file
+	 * @return a TextChange object
+	 * @see RefactoringParticipant#getTextChange(Object)
+	 */
+	public TextChange getTextChange(IFile file) {
+		return fParticipant.getTextChange(file);
+	}
+
+	/**
+	 * @return true if this is a projec rename (old and new project are set)
+	 */
+	public boolean isProjectRename() {
+		return fOldProject != null;
+	}
+
+	/**
+	 * Sets the current 0-based index. May not be out of bounds.
+	 * 
+	 * @param index
+	 * @return the model
+	 */
+	public RefactorModel setIndex(int index) {
+		Assert.isTrue(index >= 0);
+		Assert.isTrue(index < fOldTexts.size());
+		this.fIndex = index;
+		return this;
+	}
+
+	/**
+	 * Sets the old and the new project in case of project renaming.
+	 * 
+	 * @param oldProject
+	 * @param newProject
+	 * @return the model
+	 */
+	public RefactorModel setProjectRename(IProject oldProject,
+			IProject newProject) {
+		Assert.isNotNull(oldProject);
+		Assert.isNotNull(newProject);
+		fOldProject = oldProject;
+		fNewProject = newProject;
+		return this;
+	}
+
+	/**
+	 * Sets the RefactoringParticipant.
+	 * 
+	 * @param pParticipant
+	 * @return the model
+	 * @see RefactoringParticipant
+	 */
+	public RefactorModel setRefactorParticipant(
+			RefactoringParticipant pParticipant) {
+		this.fParticipant = pParticipant;
+		return this;
+	}
+}
diff --git a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorParticipantDelegate.java b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorParticipantDelegate.java
index de104ff..ba25f77 100644
--- a/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorParticipantDelegate.java
+++ b/bundles/org.eclipse.e4.tools.emf.editor3x/src/org/eclipse/e4/tools/emf/editor3x/RefactorParticipantDelegate.java
@@ -7,22 +7,23 @@
  *
  * Contributors:
  *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
+ *     Wim Jongman <wim.jongman@remainsoftware.com>  Bug 432892: Eclipse 4 Application does not work after renaming the project name
  ******************************************************************************/
 package org.eclipse.e4.tools.emf.editor3x;
 
 import java.util.HashMap;
 import java.util.Map;
-import java.util.regex.Pattern;
 
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.ltk.core.refactoring.Change;
 import org.eclipse.ltk.core.refactoring.CompositeChange;
 import org.eclipse.ltk.core.refactoring.TextChange;
 import org.eclipse.ltk.core.refactoring.TextFileChange;
-import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
+import org.eclipse.pde.internal.ui.refactoring.MovedTextFileChange;
 import org.eclipse.search.core.text.TextSearchEngine;
 import org.eclipse.search.core.text.TextSearchMatchAccess;
 import org.eclipse.search.core.text.TextSearchRequestor;
@@ -32,16 +33,36 @@
 import org.eclipse.text.edits.TextEditGroup;
 
 class RefactorParticipantDelegate {
-	public static Change createChange(IProgressMonitor pm,
-			final RefactoringParticipant p, String oldUrl, final String newUrl)
+
+	private static final String E4_MODEL_CHANGES = "Eclipse 4 Application Model Changes";
+
+	/**
+	 * Creates a set of changes and returns a new {@link CompositeChange} or
+	 * adds the changes to the passed {@link CompositeChange}.
+	 * 
+	 * @param pProgressMonitor
+	 * @param pParticipant
+	 * @param pOldUrl
+	 *            String[] containing the old texts
+	 * @param pNewUrl
+	 *            String[] containing the new texts
+	 * @param pNewProject
+	 *            The name of the project if this is a project change else null.
+	 * @return a set of changes in a {@link CompositeChange}
+	 * @throws CoreException
+	 * @throws OperationCanceledException
+	 */
+	public static CompositeChange createChange(
+			IProgressMonitor pProgressMonitor, final RefactorModel pModel)
 			throws CoreException, OperationCanceledException {
-		String[] filenames = { "*.e4xmi" };
+
+		String[] filenames = { "*.e4xmi", "plugin.xml" };
 		FileTextSearchScope scope = FileTextSearchScope.newWorkspaceScope(
 				filenames, false);
-		Pattern pattern = Pattern.compile(oldUrl);
 
 		final Map<IFile, TextFileChange> changes = new HashMap<IFile, TextFileChange>();
 		TextSearchRequestor searchRequestor = new TextSearchRequestor() {
+
 			@Override
 			public boolean acceptPatternMatch(TextSearchMatchAccess matchAccess)
 					throws CoreException {
@@ -49,30 +70,64 @@
 				TextFileChange change = changes.get(file);
 
 				if (change == null) {
-					TextChange textChange = p.getTextChange(file);
+					TextChange textChange = pModel.getTextChange(file);
 					if (textChange != null) {
 						return false;
 					}
-					change = new TextFileChange(file.getName(), file);
-					change.setEdit(new MultiTextEdit());
-					changes.put(file, change);
+
+					if (pModel.isProjectRename()
+							&& file.getProject().equals(pModel.getOldProject())) {
+						// The project/resources get refactored before the
+						// TextChange is applied, therefore we need their
+						// future locations
+						IProject newProject = pModel.getNewProject();
+
+						// If the model is in a non-standard location the
+						// new project will keep that location, only the project
+						// will be changed
+						IPath oldFile = file.getFullPath().removeFirstSegments(
+								1);
+						IFile newFile = newProject.getFile(oldFile);
+
+						change = new MovedTextFileChange(file.getName(),
+								newFile, file);
+						change.setEdit(new MultiTextEdit());
+						changes.put(file, change);
+
+					} else {
+						change = new TextFileChange(file.getName(), file);
+						change.setEdit(new MultiTextEdit());
+						changes.put(file, change);
+					}
 				}
+
 				ReplaceEdit edit = new ReplaceEdit(
 						matchAccess.getMatchOffset(),
-						matchAccess.getMatchLength(), newUrl);
+						matchAccess.getMatchLength(),
+						pModel.getNewTextCurrentIndex());
 				change.addEdit(edit);
-				change.addTextEditGroup(new TextEditGroup(
-						"Eclipse 4 Application Model Changes", edit)); //$NON-NLS-1$
+				change.addTextEditGroup(new TextEditGroup(E4_MODEL_CHANGES,
+						edit)); //$NON-NLS-1$
 				return true;
 			}
 		};
-		TextSearchEngine.create().search(scope, searchRequestor, pattern, pm);
+
+		CompositeChange result;
+		TextSearchEngine searchEngine = TextSearchEngine.create();
+		for (int count = pModel.getRenameCount(); count > 0; count--) {
+			pModel.setIndex(count - 1);
+			searchEngine.search(
+					scope,
+					searchRequestor,
+					TextSearchEngine.createPattern(
+							pModel.getOldTextCurrentIndex(), true, false),
+					pProgressMonitor);
+		}
 
 		if (changes.isEmpty())
 			return null;
 
-		CompositeChange result = new CompositeChange(
-				"Eclipse 4 Application Model Changes"); //$NON-NLS-1$
+		result = new CompositeChange(E4_MODEL_CHANGES); //$NON-NLS-1$
 		for (TextFileChange c : changes.values()) {
 			result.add(c);
 		}