Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/rename/RenameRefactoring.java')
-rw-r--r--org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/rename/RenameRefactoring.java332
1 files changed, 332 insertions, 0 deletions
diff --git a/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/rename/RenameRefactoring.java b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/rename/RenameRefactoring.java
new file mode 100644
index 00000000..a0e495d5
--- /dev/null
+++ b/org.eclipse.m2e.refactoring/src/org/eclipse/m2e/refactoring/rename/RenameRefactoring.java
@@ -0,0 +1,332 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.refactoring.rename;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.model.edit.pom.Model;
+import org.eclipse.m2e.model.edit.pom.util.PomResourceImpl;
+import org.eclipse.m2e.refactoring.AbstractPomRefactoring;
+import org.eclipse.m2e.refactoring.Messages;
+import org.eclipse.m2e.refactoring.PomVisitor;
+import org.eclipse.m2e.refactoring.RefactoringModelResources;
+import org.eclipse.m2e.refactoring.RefactoringModelResources.PropertyInfo;
+import org.eclipse.osgi.util.NLS;
+
+
+/**
+ * Rename artifact refactoring implementation
+ *
+ * @author Anton Kraev
+ */
+@SuppressWarnings("unchecked")
+public class RenameRefactoring extends AbstractPomRefactoring {
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[] {};
+ private static final String VERSION = "version"; //$NON-NLS-1$
+ private static final String GETVERSION = Messages.RenameRefactoring_1;
+ private static final String ARTIFACT_ID = "artifactId"; //$NON-NLS-1$
+ private static final String GETARTIFACT_ID = "getArtifactId"; //$NON-NLS-1$
+ private static final String GROUP_ID = "groupId"; //$NON-NLS-1$
+ private static final String GETGROUP_ID = "getGroupId"; //$NON-NLS-1$
+
+ // this page contains new values
+ MavenRenameWizardPage page;
+
+ // old values
+ String oldGroupId;
+ String oldArtifactId;
+ String oldVersion;
+
+ public RenameRefactoring(IFile file, MavenRenameWizardPage page) {
+ super(file);
+ this.page = page;
+ }
+
+ // gets element from effective model based on path
+ private Object getElement(Object root, Path path) {
+ if (path == null || path.path.size() == 0) {
+ return root;
+ }
+
+ PathElement current = path.path.remove(0);
+ String getterName = "get" + current.element; //$NON-NLS-1$
+
+ try {
+ Method getter = root.getClass().getMethod(getterName, new Class[] {});
+ root = getElement(getter.invoke(root, EMPTY_OBJECT_ARRAY), path);
+ if (root instanceof List) {
+ List children = (List) root;
+ for (int i=0; i<children.size(); i++) {
+ Object child = children.get(i);
+ Method artifact = child.getClass().getMethod(GETARTIFACT_ID, new Class[] {});
+ String artifactId = (String) artifact.invoke(child, EMPTY_OBJECT_ARRAY);
+ if (current.artifactId != null && !current.artifactId.equals(artifactId))
+ continue;
+
+ //found, names are correct
+ return getElement(child, path);
+ }
+ } else {
+ return getElement(root, path);
+ }
+ return null;
+ } catch(Exception ex) {
+ return null;
+ }
+ }
+
+ /**
+ * Finds all potential matched objects in model
+ */
+ private List<EObjectWithPath> scanModel(Model model, String groupId, String artifactId, String version, boolean processRoot) {
+ List<EObjectWithPath> res = new ArrayList<EObjectWithPath>();
+ Path path = new Path();
+ if(processRoot) {
+ scanObject(path, model, groupId, artifactId, version, res);
+ } else {
+ scanChildren(path, model, groupId, artifactId, version, res);
+ }
+ return res;
+ }
+
+ // add candidate objects with same artifactId
+ private List<EObjectWithPath> scanObject(Path current, EObject obj, String groupId, String artifactId, String version, List<EObjectWithPath> res) {
+ if (scanFeature(obj, ARTIFACT_ID, artifactId)) {
+ // System.out.println("found object " + obj + " : " + current);
+ res.add(new EObjectWithPath(obj, current));
+ }
+ scanChildren(current, obj, groupId, artifactId, version, res);
+ return res;
+ }
+
+ private List<EObjectWithPath> scanChildren(Path current, EObject obj, String groupId, String artifactId, String version, List<EObjectWithPath> res) {
+ Iterator<EObject> it = obj.eContents().iterator();
+ while(it.hasNext()) {
+ obj = it.next();
+ Path child = current.clone();
+ String element = obj.eContainingFeature().getName();
+ element = element.substring(0, 1).toUpperCase() + element.substring(1);
+ child.addElement(element, artifactId);
+ scanObject(child, obj, groupId, artifactId, version, res);
+ }
+ return res;
+ }
+
+ private boolean scanFeature(EObject obj, String featureName, String value) {
+ //not searching on this
+ if(value == null) {
+ return false;
+ }
+ EStructuralFeature feature = obj.eClass().getEStructuralFeature(featureName);
+ if(feature == null) {
+ return false;
+ }
+ String val = obj.eGet(feature) == null ? null : obj.eGet(feature).toString();
+ if(value.equals(val)) {
+ return true;
+ }
+ return false;
+ }
+
+ private String getValue(EObject obj, String featureName) {
+ EStructuralFeature feature = obj.eClass().getEStructuralFeature(featureName);
+ if(feature == null) {
+ return null;
+ }
+ return obj.eGet(feature) == null ? null : obj.eGet(feature).toString();
+ }
+
+ public String getNewProjectName() {
+ return page.getRenameEclipseProject()? page.getNewArtifactId(): null;
+ }
+
+ /**
+ * Applies new values in model
+ * @param editingDomain
+ * @param renameProject
+ * @throws NoSuchMethodException
+ * @throws Exception
+ */
+ public CompoundCommand applyModel(RefactoringModelResources model,
+ String newGroupId, String newArtifactId, String newVersion, boolean processRoot) throws Exception {
+ // find all affected objects in EMF model
+ List<EObjectWithPath> affected = scanModel(model.getTmpModel(), this.oldGroupId, this.oldArtifactId, this.oldVersion, processRoot);
+
+ // go through all affected objects, check in effective model
+ Iterator<EObjectWithPath> i = affected.iterator();
+ CompoundCommand command = new CompoundCommand();
+ while (i.hasNext()) {
+ EObjectWithPath obj = i.next();
+ Object effectiveObj = getElement(model.getEffective(), obj.path.clone());
+ if (effectiveObj == null) {
+ // System.out.println("cannot find effective for: " + obj.object);
+ continue;
+ }
+ Method method = effectiveObj.getClass().getMethod(GETVERSION, new Class[] {});
+ String effectiveVersion = (String) method.invoke(effectiveObj, EMPTY_OBJECT_ARRAY);
+ method = effectiveObj.getClass().getMethod(GETGROUP_ID, new Class[] {});
+ String effectiveGroupId = (String) method.invoke(effectiveObj, EMPTY_OBJECT_ARRAY);
+ // if version from effective POM is different from old version, skip it
+ if (this.oldVersion != null && !this.oldVersion.equals(effectiveVersion)) {
+ continue;
+ }
+
+ // only set groupId if effective group id is the same as old group id
+ if (oldGroupId != null && oldGroupId.equals(effectiveGroupId))
+ applyFeature(editingDomain, model, GROUP_ID, newGroupId, command, obj);
+ // set artifact id unconditionally
+ applyFeature(editingDomain, model, ARTIFACT_ID, newArtifactId, command, obj);
+ // only set version if effective version is the same (already checked by the above)
+ // and new version is not empty
+ if (!"".equals(newVersion)) { //$NON-NLS-1$
+ applyFeature(editingDomain, model, VERSION, newVersion, command, obj);
+ }
+ }
+
+ return command.isEmpty()? null: command;
+ }
+
+ // apply the value, considering properties
+ private void applyFeature(AdapterFactoryEditingDomain editingDomain, RefactoringModelResources model,
+ String feature, String newValue, CompoundCommand command, EObjectWithPath obj) {
+ PropertyInfo info = null;
+ String old = getValue(obj.object, feature);
+ if (old != null && old.startsWith("${")) { //$NON-NLS-1$
+ // this is a property, go find it
+ String pName = old.substring(2);
+ pName = pName.substring(0, pName.length() - 1).trim();
+ info = model.getProperties().get(pName);
+ }
+ if (info != null)
+ info.setNewValue(new SetCommand(editingDomain, info.getPair(), info.getPair().eClass().getEStructuralFeature("value"), newValue)); //$NON-NLS-1$
+ else
+ applyObject(editingDomain, command, obj.object, feature, newValue);
+ }
+
+ private void applyObject(AdapterFactoryEditingDomain editingDomain, CompoundCommand command, EObject obj,
+ String featureName, String value) {
+ EStructuralFeature feature = obj.eClass().getEStructuralFeature(featureName);
+ if(feature == null) {
+ return;
+ }
+ Object old = obj.eGet(feature);
+ if(old == null || old.equals(value)) {
+ return;
+ }
+ command.append(new SetCommand(editingDomain, obj, feature, value));
+ }
+
+ @Override
+ public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException {
+ PomResourceImpl resource = MavenPlugin.getDefault().getMavenModelManager().loadResource(file);
+ try {
+ Model model = (Model)resource.getContents().get(0);
+ this.oldArtifactId = model.getArtifactId();
+ this.oldGroupId = model.getGroupId();
+ this.oldVersion = model.getVersion();
+ } finally {
+ resource.unload();
+ }
+ RefactoringStatus res = new RefactoringStatus();
+ return res;
+ }
+
+ @Override
+ public String getName() {
+ return Messages.RenameRefactoring_name;
+ }
+
+ @Override
+ public PomVisitor getVisitor() {
+ return new PomVisitor() {
+
+ public CompoundCommand applyChanges(RefactoringModelResources current, IProgressMonitor pm) throws Exception {
+ //process <project> element only for the refactored file itself
+ boolean processRoot = current.getPomFile().equals(file);
+ return RenameRefactoring.this.applyModel(current, page.getNewGroupId(),
+ page.getNewArtifactId(), page.getNewVersion(), processRoot);
+ }
+ };
+ }
+
+ static class Path {
+ List<PathElement> path = new ArrayList<PathElement>();
+
+ public void addElement(String element, String artifactId) {
+ path.add(new PathElement(element, artifactId));
+ }
+
+ public String toString() {
+ return path.toString();
+ }
+
+ public Path clone() {
+ Path res = new Path();
+ res.path = new ArrayList<PathElement>(this.path);
+ return res;
+ }
+ }
+
+ // path (built during traversal of EMF model, used to find in effective model)
+ static class PathElement {
+ String element;
+ String artifactId;
+
+ public PathElement(String element, String artifactId) {
+ this.element = element;
+ this.artifactId = artifactId;
+ }
+
+ public String toString() {
+ return "/" + element + "[artifactId=" + artifactId + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+
+ static class EObjectWithPath {
+ public EObject object;
+ public Path path;
+
+ public EObjectWithPath(EObject object, Path path) {
+ this.object = object;
+ this.path = path;
+ }
+ }
+
+ // XXX move stuff UP after implementing another refactoring
+ // after moving up, use this
+ interface ScanVisitor {
+ public boolean interested(EObject obj);
+ }
+
+ public boolean scanAllArtifacts() {
+ return true;
+ }
+
+ public String getTitle() {
+ return NLS.bind(Messages.RenameRefactoring_title, file.getParent().getName());
+ }
+
+}

Back to the top