/******************************************************************************* * Copyright (c) 2012 VMWare, 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: * VMWare, Inc. - initial API and implementation *******************************************************************************/ package org.grails.ide.eclipse.refactoring.rename.action; import java.util.Collection; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks; import org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor; import org.eclipse.jdt.internal.corext.refactoring.rename.RenameMethodProcessor; import org.eclipse.jdt.internal.corext.refactoring.rename.RenameNonVirtualMethodProcessor; import org.eclipse.jdt.internal.corext.refactoring.rename.RenameVirtualMethodProcessor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.ltk.core.refactoring.participants.RenameProcessor; import org.grails.ide.eclipse.core.GrailsCoreActivator; import org.grails.ide.eclipse.core.internal.GrailsNature; import org.grails.ide.eclipse.refactoring.util.RefactoringUtils; /** * @author Kris De Volder * @since 2.8 */ public class GSPRenameParticipant extends GrailsActionOrViewRenameParticipant { private static final String GSP_EXT = ".gsp"; private IFile gspFile; // The gspFile that's being renamed public GSPRenameParticipant() {} @Override protected boolean initialize(Object element) { String newActionName = getArguments().getNewName(); if (newActionName.endsWith(GSP_EXT)) { newActionName = newActionName.substring(0, newActionName.length()-GSP_EXT.length()); setNewActionName(newActionName); if (element instanceof IFile) { gspFile = (IFile) element; String name = gspFile.getName(); if (name.endsWith(GSP_EXT)) { IProject project = gspFile.getProject(); if (project!=null) { if (GrailsNature.isGrailsProject(project)) { setProject(project); return parsePath(); } } } } } return false; } @Override public String getName() { return "Rename Grails View Participant"; } /** * @return true if path follows expected pattern and the participant should be triggered. */ public boolean parsePath() { //Assuming the following pattern for the path: // "/<project>/grails-app/views/<controller>/<action>.gsp" IPath path = gspFile.getFullPath(); if (path.segmentCount()==5 && path.segment(1).equals("grails-app") && path.segment(2).equals("views")) { setTargetControllerName(path.segment(3)); String actionName = path.segment(4); if (actionName.endsWith(GSP_EXT)) { setOldActionName(actionName.substring(0, actionName.length()-GSP_EXT.length())); return true; } } return false; } @Override public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException { final RefactoringStatus status = new RefactoringStatus(); rewriteActionReferences(status); renameAction(context, status); return status; } public void renameAction(CheckConditionsContext context, final RefactoringStatus status) { try { Collection<? extends IMember> actions = getActions(getTargetController(), getOldActionName()); IMember targetAction = null; for (IMember action : actions) { if (targetAction==null) { targetAction = action; } else { status.addError("More than one controller action with name '"+getOldActionName() +"' in '"+getTargetControllerClassName()+"'"); } } if (targetAction!=null) { renameAction(targetAction, status, context); } } catch (JavaModelException e) { GrailsCoreActivator.log(e); status.addError(e.getMessage()); } } private void renameAction(IMember target, RefactoringStatus status, CheckConditionsContext context) { try { RenameProcessor processor = null; if (target instanceof IMethod) { processor = renameMethodProcessor((IMethod) target, status, context); } else if (target instanceof IField) { processor = renameFieldProcessor((IField) target, status, context); } else { status.addError("Action is neither a field nor a method, this doesn't make sense: "+target.getElementName(), RefactoringUtils.statusContext(target)); } if (processor!=null) { status.merge(processor.checkInitialConditions(new NullProgressMonitor())); status.merge(processor.checkFinalConditions(new NullProgressMonitor(), context)); changes.add(processor.createChange(new NullProgressMonitor())); } } catch (Exception e) { GrailsCoreActivator.log(e); status.addFatalError("Unexpected error see error log for details"); } } private RenameProcessor renameFieldProcessor(IField target, RefactoringStatus status, CheckConditionsContext context) { RenameFieldProcessor processor = new RenameFieldProcessor(target); processor.setNewElementName(getNewActionName()); return processor; } private RenameProcessor renameMethodProcessor(IMethod target, RefactoringStatus status, CheckConditionsContext context) throws JavaModelException { RenameMethodProcessor processor = null; if (MethodChecks.isVirtual(target)) { processor = new RenameVirtualMethodProcessor(target); } else { status.addWarning("Action is a non-virtual method: '"+target.getElementName()+"'", RefactoringUtils.statusContext(target)); processor = new RenameNonVirtualMethodProcessor(target); } processor.setNewElementName(getNewActionName()); processor.setUpdateReferences(true); //TODO: True? return processor; } }