aboutsummaryrefslogtreecommitdiffstats
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com
diff options
context:
space:
mode:
authorRaphael Moll <ralf@android.com>2010-11-26 22:43:40 -0800
committerRaphael Moll <ralf@android.com>2010-11-26 22:43:40 -0800
commit681d85054670b922fcc311246eb1d2b5254b7584 (patch)
tree296c06eea24f3bcd7839d8ae9a1f77c122baf3ca /eclipse/plugins/com.android.ide.eclipse.adt/src/com
parent9bff2af74a7d6c4034152e76e90993160b14c458 (diff)
downloadsdk-681d85054670b922fcc311246eb1d2b5254b7584.zip
sdk-681d85054670b922fcc311246eb1d2b5254b7584.tar.gz
sdk-681d85054670b922fcc311246eb1d2b5254b7584.tar.bz2
ADT: cleanup RenamePackage action.
Move it to the refactoring package. Split action code from refactoring code. No change in functionality nor invocation (via context menu project > Android Tools.) Change-Id: Ieec945b37fdd33d497bf745d207eb5d6b5445d9f
Diffstat (limited to 'eclipse/plugins/com.android.ide.eclipse.adt/src/com')
-rwxr-xr-x[-rw-r--r--]eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoring.java (renamed from eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/RenamePackageAction.java)306
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoringWizard.java35
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/RenamePackageAction.java174
3 files changed, 290 insertions, 225 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/RenamePackageAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoring.java
index f06e00d..4a9a66e 100644..100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/RenamePackageAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoring.java
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package com.android.ide.eclipse.adt.internal.actions;
+package com.android.ide.eclipse.adt.internal.refactorings.renamepackage;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AndroidConstants;
-import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.xml.AndroidManifest;
-import com.android.sdklib.xml.ManifestData;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -30,7 +28,6 @@ import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
@@ -47,29 +44,17 @@ import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.dialogs.IInputValidator;
-import org.eclipse.jface.dialogs.InputDialog;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.window.Window;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextEditChangeGroup;
import org.eclipse.ltk.core.refactoring.TextFileChange;
-import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
-import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditGroup;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-import org.eclipse.ui.IWorkbenchWindow;
-import org.eclipse.ui.IWorkbenchWindowActionDelegate;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
@@ -82,157 +67,84 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
/**
- * Refactoring steps:
- * <ol>
- * <li>Update the "package" attribute of the &lt;manifest&gt; tag with the new
- * name.</li>
- * <li>Replace all values for the "android:name" attribute in the
- * &lt;application&gt; and "component class" (&lt;activity&gt;, &lt;service&gt;,
- * &lt;receiver&gt;, and &lt;provider&gt;) tags with the non-shorthand version
- * of the class name</li>
- * <li>Replace package resource imports (*.R) in .java files</li>
- * <li>Update package name in the namespace declarations (e.g. "xmlns:app")
- * used for custom styleable attributes in layout resource files</li>
- * </ol>
- * Caveat: Sometimes it is necessary to perform a project-wide
- * "Organize Imports" afterwards. (CTRL+SHIFT+O when a project has active
- * selection)
+ * Wrapper class defining the stages of the refactoring process
*/
-public class RenamePackageAction implements IObjectActionDelegate {
+@SuppressWarnings("restriction")
+class ApplicationPackageNameRefactoring extends Refactoring {
- private ISelection mSelection;
-
- private Name mOldPackageName, mNewPackageName;
-
- public final static String[] MAIN_COMPONENT_TYPES = {
- AndroidManifest.NODE_ACTIVITY, AndroidManifest.NODE_SERVICE,
- AndroidManifest.NODE_RECEIVER, AndroidManifest.NODE_PROVIDER,
- AndroidManifest.NODE_APPLICATION
- };
+ private final IProject mProject;
+ private final Name mOldPackageName;
+ private final Name mNewPackageName;
List<String> MAIN_COMPONENT_TYPES_LIST = Arrays.asList(MAIN_COMPONENT_TYPES);
public final static String ANDROID_NS_URI = SdkConstants.NS_RESOURCES;
-
public final static String NAMESPACE_DECLARATION_PREFIX = "xmlns:"; //$NON-NLS-1$
- IWorkbenchPart mTargetPart;
- /**
- * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
- */
- public void setActivePart(IAction action, IWorkbenchPart targetPart) {
- mTargetPart = targetPart;
+ ApplicationPackageNameRefactoring(
+ IProject project,
+ Name oldPackageName,
+ Name newPackageName) {
+ mProject = project;
+ mOldPackageName = oldPackageName;
+ mNewPackageName = newPackageName;
}
- public void selectionChanged(IAction action, ISelection selection) {
- mSelection = selection;
- }
+ @Override
+ public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
+ throws CoreException, OperationCanceledException {
+
+ // Accurate refactoring of the "shorthand" names in
+ // AndroidManifest.xml depends on not having compilation errors.
+ if (mProject.findMaxProblemSeverity(
+ IMarker.PROBLEM,
+ true,
+ IResource.DEPTH_INFINITE) == IMarker.SEVERITY_ERROR) {
+ return RefactoringStatus
+ .createFatalErrorStatus("Fix the errors in your project, first.");
+ }
- /**
- * @see IWorkbenchWindowActionDelegate#init
- */
- public void init(IWorkbenchWindow window) {
- // pass
+ return new RefactoringStatus();
}
- public void run(IAction action) {
-
- // Prompt for refactoring on the selected project
- if (mSelection instanceof IStructuredSelection) {
- for (Iterator<?> it = ((IStructuredSelection) mSelection).iterator(); it.hasNext();) {
- Object element = it.next();
- IProject project = null;
- if (element instanceof IProject) {
- project = (IProject) element;
- } else if (element instanceof IAdaptable) {
- project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
- }
- if (project != null) {
- // TODO/FIXME Uncomment this when support for Eclipse 3.4 is dropped!
- /*
- // It is advisable that the user saves before proceeding,
- // revealing any compilation errors. The following lines
- // enforce a save as a convenience.
- RefactoringSaveHelper save_helper = new RefactoringSaveHelper(
- RefactoringSaveHelper.SAVE_ALL_ALWAYS_ASK);
- if (save_helper.saveEditors(AdtPlugin.getDisplay().getActiveShell())) {
- promptNewName(project);
- }
- */
+ @Override
+ public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
+ throws OperationCanceledException {
- promptNewName(project);
- }
- }
- }
+ return new RefactoringStatus();
}
- /*
- * Validate the new package name and start the refactoring wizard
- */
- private void promptNewName(final IProject project) {
-
- ManifestData manifestData = AndroidManifestHelper.parseForData(project);
- if (manifestData == null) {
- return;
- }
-
- final String old_package_name_string = manifestData.getPackage();
-
- final AST ast_validator = AST.newAST(AST.JLS3);
- mOldPackageName = ast_validator.newName(old_package_name_string);
-
- IInputValidator validator = new IInputValidator() {
-
- public String isValid(String newText) {
- try {
- ast_validator.newName(newText);
- } catch (IllegalArgumentException e) {
- return "Illegal package name.";
- }
-
- if (newText.equals(old_package_name_string))
- return "No change.";
- else
- return null;
- }
- };
+ @Override
+ public Change createChange(IProgressMonitor pm) throws CoreException,
+ OperationCanceledException {
- InputDialog dialog = new InputDialog(AdtPlugin.getDisplay().getActiveShell(),
- "Rename Application Package", "Enter new package name:", old_package_name_string,
- validator);
-
- if (dialog.open() == Window.OK) {
- mNewPackageName = ast_validator.newName(dialog.getValue());
- initiateAndroidPackageRefactoring(project);
- }
+ // Traverse all files in the project, building up a list of changes
+ JavaFileVisitor fileVisitor = new JavaFileVisitor();
+ mProject.accept(fileVisitor);
+ return fileVisitor.getChange();
}
+ @Override
+ public String getName() {
+ return "AndroidPackageNameRefactoring"; //$NON-NLS-1$
+ }
- private void initiateAndroidPackageRefactoring(final IProject project) {
-
- Refactoring package_name_refactoring = new ApplicationPackageNameRefactoring(project);
+ public final static String[] MAIN_COMPONENT_TYPES = {
+ AndroidManifest.NODE_ACTIVITY, AndroidManifest.NODE_SERVICE,
+ AndroidManifest.NODE_RECEIVER, AndroidManifest.NODE_PROVIDER,
+ AndroidManifest.NODE_APPLICATION
+ };
- ApplicationPackageNameRefactoringWizard wizard =
- new ApplicationPackageNameRefactoringWizard(package_name_refactoring);
- RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
- try {
- op.run(AdtPlugin.getDisplay().getActiveShell(), package_name_refactoring.getName());
- } catch (InterruptedException e) {
- Status s = new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, e.getMessage(), e);
- AdtPlugin.getDefault().getLog().log(s);
- }
- }
TextEdit updateJavaFileImports(CompilationUnit cu) {
- ImportVisitor import_visitor = new ImportVisitor(cu.getAST());
- cu.accept(import_visitor);
- TextEdit rewritten_imports = import_visitor.getTextEdit();
+ ImportVisitor importVisitor = new ImportVisitor(cu.getAST());
+ cu.accept(importVisitor);
+ TextEdit rewrittenImports = importVisitor.getTextEdit();
// If the import of R was potentially implicit, insert an import statement
if (cu.getPackage().getName().getFullyQualifiedName()
@@ -243,7 +155,7 @@ public class RenamePackageAction implements IObjectActionDelegate {
+ AndroidConstants.FN_RESOURCE_BASE);
try {
- rewritten_imports.addChild( irw.rewriteImports(null) );
+ rewrittenImports.addChild( irw.rewriteImports(null) );
} catch (MalformedTreeException e) {
Status s = new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, e.getMessage(), e);
AdtPlugin.getDefault().getLog().log(s);
@@ -253,7 +165,7 @@ public class RenamePackageAction implements IObjectActionDelegate {
}
}
- return rewritten_imports;
+ return rewrittenImports;
}
// XML utility functions
@@ -292,6 +204,10 @@ public class RenamePackageAction implements IObjectActionDelegate {
AdtPlugin.getDefault().getLog().log(s);
}
+ if (sdoc == null) {
+ return null;
+ }
+
TextFileChange xmlChange = new TextFileChange("XML resource file edit", file);
xmlChange.setTextType(AndroidConstants.EXT_XML);
@@ -325,14 +241,16 @@ public class RenamePackageAction implements IObjectActionDelegate {
} else if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(type)) {
// Check this is the attribute and the original string
- if (lastAttrName.startsWith(NAMESPACE_DECLARATION_PREFIX)) {
+ if (lastAttrName != null &&
+ lastAttrName.startsWith(NAMESPACE_DECLARATION_PREFIX)) {
String lastAttrValue = region.getText(subRegion);
if (oldAppNamespaceString.equals(stripQuotes(lastAttrValue))) {
// Found an occurrence. Create a change for it.
- TextEdit edit = new ReplaceEdit(region.getStartOffset()
- + subRegion.getStart(), subRegion.getTextLength(),
+ TextEdit edit = new ReplaceEdit(
+ region.getStartOffset() + subRegion.getStart(),
+ subRegion.getTextLength(),
addQuotes(newAppNamespaceString));
TextEditGroup editGroup = new TextEditGroup(
"Replace package name in custom namespace prefix", edit);
@@ -377,6 +295,10 @@ public class RenamePackageAction implements IObjectActionDelegate {
AdtPlugin.getDefault().getLog().log(s);
}
+ if (sdoc == null) {
+ return null;
+ }
+
TextFileChange xmlChange = new TextFileChange("Make Manifest edits", file);
xmlChange.setTextType(AndroidConstants.EXT_XML);
@@ -414,7 +336,8 @@ public class RenamePackageAction implements IObjectActionDelegate {
} else if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(type)) {
String lastAttrValue = region.getText(subRegion);
- if (lastAttrName.startsWith(NAMESPACE_DECLARATION_PREFIX)) {
+ if (lastAttrName != null &&
+ lastAttrName.startsWith(NAMESPACE_DECLARATION_PREFIX)) {
// Resolves the android namespace prefix for this file
if (ANDROID_NS_URI.equals(stripQuotes(lastAttrValue))) {
@@ -423,9 +346,7 @@ public class RenamePackageAction implements IObjectActionDelegate {
android_name_attribute = android_namespace_prefix + ':'
+ AndroidManifest.ATTRIBUTE_NAME;
}
- }
-
- else if (AndroidManifest.NODE_MANIFEST.equals(lastTagName)
+ } else if (AndroidManifest.NODE_MANIFEST.equals(lastTagName)
&& AndroidManifest.ATTRIBUTE_PACKAGE.equals(lastAttrName)) {
// Found an occurrence. Create a change for it.
@@ -437,6 +358,7 @@ public class RenamePackageAction implements IObjectActionDelegate {
editGroups.add(new TextEditGroup("Change Android package name", edit));
} else if (MAIN_COMPONENT_TYPES_LIST.contains(lastTagName)
+ && lastAttrName != null
&& lastAttrName.equals(android_name_attribute)) {
String package_path = stripQuotes(lastAttrValue);
@@ -490,6 +412,7 @@ public class RenamePackageAction implements IObjectActionDelegate {
return change;
}
+ @SuppressWarnings("unused")
public boolean visit(IResource resource) throws CoreException {
if (resource instanceof IFile) {
IFile file = (IFile) resource;
@@ -524,16 +447,12 @@ public class RenamePackageAction implements IObjectActionDelegate {
} else {
// Currently we only support Android resource XML files,
- // so they must have a path
- // similar to
- // project/res/<type>[-<configuration>]/*.xml
- // There is no support for sub folders, so the segment
- // count must be 4.
+ // so they must have a path similar to
+ // project/res/<type>[-<configuration>]/*.xml
+ // There is no support for sub folders, so the segment count must be 4.
// We don't need to check the type folder name because
- // a/ we only accept
- // an AndroidXmlEditor source and b/ aapt generates a
- // compilation error for
- // unknown folders.
+ // a/ we only accept an AndroidXmlEditor source and
+ // b/ aapt generates a compilation error for unknown folders.
IPath path = file.getFullPath();
// check if we are inside the project/res/* folder.
if (path.segmentCount() == 4) {
@@ -585,13 +504,13 @@ public class RenamePackageAction implements IObjectActionDelegate {
@Override
public boolean visit(ImportDeclaration id) {
- Name import_name = id.getName();
- if (import_name.isQualifiedName()) {
- QualifiedName qualified_import_name = (QualifiedName) import_name;
+ Name importName = id.getName();
+ if (importName.isQualifiedName()) {
+ QualifiedName qualifiedImportName = (QualifiedName) importName;
- if (qualified_import_name.getName().getIdentifier()
+ if (qualifiedImportName.getName().getIdentifier()
.equals(AndroidConstants.FN_RESOURCE_BASE)) {
- mRewriter.replace(qualified_import_name.getQualifier(), mNewPackageName,
+ mRewriter.replace(qualifiedImportName.getQualifier(), mNewPackageName,
null);
}
}
@@ -599,67 +518,4 @@ public class RenamePackageAction implements IObjectActionDelegate {
return true;
}
}
-
- class ApplicationPackageNameRefactoringWizard extends RefactoringWizard {
-
- public ApplicationPackageNameRefactoringWizard(Refactoring refactoring) {
- super(refactoring, 0);
- }
-
- @Override
- protected void addUserInputPages() {
- }
- }
-
- /*
- * Wrapper class defining the stages of the refactoring process
- */
- class ApplicationPackageNameRefactoring extends Refactoring {
-
- IProject mProject;
-
- ApplicationPackageNameRefactoring(final IProject project) {
- mProject = project;
- }
-
- @Override
- public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException,
- OperationCanceledException {
-
- return new RefactoringStatus();
- }
-
- @Override
- public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException,
- OperationCanceledException {
-
- // Accurate refactoring of the "shorthand" names in
- // AndroidManifest.xml
- // depends on not having compilation errors.
- if (mProject.findMaxProblemSeverity(
- IMarker.PROBLEM,
- true,
- IResource.DEPTH_INFINITE) == IMarker.SEVERITY_ERROR) {
- return RefactoringStatus
- .createFatalErrorStatus("Fix the errors in your project, first.");
- }
-
- return new RefactoringStatus();
- }
-
- @Override
- public Change createChange(IProgressMonitor pm) throws CoreException,
- OperationCanceledException {
-
- // Traverse all files in the project, building up a list of changes
- JavaFileVisitor file_visitor = new JavaFileVisitor();
- mProject.accept(file_visitor);
- return file_visitor.getChange();
- }
-
- @Override
- public String getName() {
- return "AndroidPackageNameRefactoring"; //$NON-NLS-1$
- }
- }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoringWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoringWizard.java
new file mode 100755
index 0000000..3651855
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/ApplicationPackageNameRefactoringWizard.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.refactorings.renamepackage;
+
+import org.eclipse.ltk.core.refactoring.Refactoring;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
+
+/**
+ * @see RenamePackageAction
+ */
+class ApplicationPackageNameRefactoringWizard extends RefactoringWizard {
+
+ public ApplicationPackageNameRefactoringWizard(Refactoring refactoring) {
+ super(refactoring, 0);
+ }
+
+ @Override
+ protected void addUserInputPages() {
+ }
+}
+
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/RenamePackageAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/RenamePackageAction.java
new file mode 100644
index 0000000..dfbaf55
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/renamepackage/RenamePackageAction.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.internal.refactorings.renamepackage;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
+import com.android.sdklib.xml.ManifestData;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+import org.eclipse.ltk.core.refactoring.Refactoring;
+import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+import java.util.Iterator;
+
+/**
+ * Refactoring steps:
+ * <ol>
+ * <li>Update the "package" attribute of the &lt;manifest&gt; tag with the new
+ * name.</li>
+ * <li>Replace all values for the "android:name" attribute in the
+ * &lt;application&gt; and "component class" (&lt;activity&gt;, &lt;service&gt;,
+ * &lt;receiver&gt;, and &lt;provider&gt;) tags with the non-shorthand version
+ * of the class name</li>
+ * <li>Replace package resource imports (*.R) in .java files</li>
+ * <li>Update package name in the namespace declarations (e.g. "xmlns:app")
+ * used for custom styleable attributes in layout resource files</li>
+ * </ol>
+ * Caveat: Sometimes it is necessary to perform a project-wide
+ * "Organize Imports" afterwards. (CTRL+SHIFT+O when a project has active
+ * selection)
+ */
+public class RenamePackageAction implements IObjectActionDelegate {
+
+ private ISelection mSelection;
+ @SuppressWarnings("unused") private IWorkbenchPart mTargetPart; // TODO cleanup
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ mTargetPart = targetPart;
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ mSelection = selection;
+ }
+
+ /**
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window) {
+ // pass
+ }
+
+ public void run(IAction action) {
+
+ // Prompt for refactoring on the selected project
+ if (mSelection instanceof IStructuredSelection) {
+ for (Iterator<?> it = ((IStructuredSelection) mSelection).iterator(); it.hasNext();) {
+ Object element = it.next();
+ IProject project = null;
+ if (element instanceof IProject) {
+ project = (IProject) element;
+ } else if (element instanceof IAdaptable) {
+ project = (IProject) ((IAdaptable) element).getAdapter(IProject.class);
+ }
+ if (project != null) {
+ // TODO/FIXME Uncomment this when support for Eclipse 3.4 is dropped!
+ /*
+ // It is advisable that the user saves before proceeding,
+ // revealing any compilation errors. The following lines
+ // enforce a save as a convenience.
+ RefactoringSaveHelper save_helper = new RefactoringSaveHelper(
+ RefactoringSaveHelper.SAVE_ALL_ALWAYS_ASK);
+ if (save_helper.saveEditors(AdtPlugin.getDisplay().getActiveShell())) {
+ promptNewName(project);
+ }
+ */
+
+ promptNewName(project);
+ }
+ }
+ }
+ }
+
+ /*
+ * Validate the new package name and start the refactoring wizard
+ */
+ private void promptNewName(final IProject project) {
+
+ ManifestData manifestData = AndroidManifestHelper.parseForData(project);
+ if (manifestData == null) {
+ return;
+ }
+
+ final String oldPackageNameString = manifestData.getPackage();
+
+ final AST astValidator = AST.newAST(AST.JLS3);
+ Name oldPackageName = astValidator.newName(oldPackageNameString);
+
+ IInputValidator validator = new IInputValidator() {
+
+ public String isValid(String newText) {
+ try {
+ astValidator.newName(newText);
+ } catch (IllegalArgumentException e) {
+ return "Illegal package name.";
+ }
+
+ if (newText.equals(oldPackageNameString))
+ return "No change.";
+ else
+ return null;
+ }
+ };
+
+ InputDialog dialog = new InputDialog(AdtPlugin.getDisplay().getActiveShell(),
+ "Rename Application Package", "Enter new package name:", oldPackageNameString,
+ validator);
+
+ if (dialog.open() == Window.OK) {
+ Name newPackageName = astValidator.newName(dialog.getValue());
+ initiateAndroidPackageRefactoring(project, oldPackageName, newPackageName);
+ }
+ }
+
+
+ private void initiateAndroidPackageRefactoring(
+ final IProject project,
+ Name oldPackageName,
+ Name newPackageName) {
+
+ Refactoring package_name_refactoring =
+ new ApplicationPackageNameRefactoring(project, oldPackageName, newPackageName);
+
+ ApplicationPackageNameRefactoringWizard wizard =
+ new ApplicationPackageNameRefactoringWizard(package_name_refactoring);
+ RefactoringWizardOpenOperation op = new RefactoringWizardOpenOperation(wizard);
+ try {
+ op.run(AdtPlugin.getDisplay().getActiveShell(), package_name_refactoring.getName());
+ } catch (InterruptedException e) {
+ Status s = new Status(Status.ERROR, AdtPlugin.PLUGIN_ID, e.getMessage(), e);
+ AdtPlugin.getDefault().getLog().log(s);
+ }
+ }
+}