blob: 5adbb91367c4590359014c5a3ea860bcf2095194 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.ui.refactoring;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.util.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.ui.IEditorPart;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.corext.refactoring.base.ChangeAbortException;
import org.eclipse.jdt.internal.corext.refactoring.base.ChangeContext;
import org.eclipse.jdt.internal.corext.refactoring.base.IChange;
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus;
import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
import org.eclipse.jdt.internal.ui.JavaPlugin;
/**
* Operation that, when performed, performes a change to the workbench.
*/
public class PerformChangeOperation implements IRunnableWithProgress {
private IChange fChange;
private ChangeContext fChangeContext;
private CreateChangeOperation fCreateChangeOperation;
private int fCheckPassedSeverity;
private boolean fChangeExecuted;
/**
* Creates a new perform change operation instance for the given change.
*
* @param change the change to be applied to the workbench
*/
public PerformChangeOperation(IChange change) {
fChange= change;
Assert.isNotNull(fChange);
}
/**
* Creates a new perform change operation for the given create change operation.
* When executed, a new change is created using the passed instance.
*
* @param op the <code>CreateChangeOperation</code> used to create a new
* change object
*/
public PerformChangeOperation(CreateChangeOperation op) {
fCreateChangeOperation= op;
Assert.isNotNull(fCreateChangeOperation);
fCheckPassedSeverity= RefactoringStatus.INFO;
}
/**
* Returns <code>true</code> if the change has been executed. Otherwise <code>false</code>
* is returned.
*
* @return <code>true</code> if the change has been executed, otherwise
* <code>false</code>
*/
public boolean changeExecuted() {
return fChangeExecuted;
}
/**
* Returns the change used by this operation. This is either the change passed to
* the constructor or the one create by the <code>CreateChangeOperation</code>.
* Method returns <code>null</code> if the create operation did not create
* the change.
*
* @return the change used by this operation or <code>null</code> if no change
* has been created
*/
public IChange getChange() {
return fChange;
}
public RefactoringStatus getStatus() {
return fCreateChangeOperation != null ? fCreateChangeOperation.getStatus() : null;
}
/**
* Sets the check passed severity value. This value is used to deceide whether the
* condition check, executed if a change is to be created, is interpreted as passed
* or not. The condition check is considered to be passed if the refactoring status's
* severity is less or equal the given severity. The given value must be smaller
* than <code>RefactoringStatus.FATAL</code>.
*
* @param severity the severity value considered to be "ok".
*/
public void setCheckPassedSeverity(int severity) {
fCheckPassedSeverity= severity;
Assert.isTrue (fCheckPassedSeverity < RefactoringStatus.FATAL);
}
/**
* Sets the change context used to execute the change. The given context is passed
* to the method <code>IChange.perform</code>.
*
* @param context the change context to use
* @see IChange#perform(ChangeContext, IProgressMonitor)
*/
public void setChangeContext(ChangeContext context) {
fChangeContext= context;
Assert.isNotNull(fChangeContext);
}
/* (non-Javadoc)
* Method declard in IRunnableWithProgress
*/
public void run(IProgressMonitor pm) throws InvocationTargetException, InterruptedException {
try{
fChangeExecuted= false;
if (createChange()) {
pm.beginTask("", 2); //$NON-NLS-1$
fCreateChangeOperation.run(new SubProgressMonitor(pm, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
fChange= fCreateChangeOperation.getChange();
RefactoringStatus status= fCreateChangeOperation.getStatus();
int conditionCheckingStyle= fCreateChangeOperation.getConditionCheckingStyle();
if (fChange != null &&
(conditionCheckingStyle == CreateChangeOperation.CHECK_NONE ||
status != null && status.getSeverity() <= fCheckPassedSeverity)) {
executeChange(new SubProgressMonitor(pm, 1, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK));
fChangeExecuted= true;
} else {
pm.worked(1);
}
} else {
executeChange(pm);
fChangeExecuted= true;
}
} catch (CoreException e) {
throw new InvocationTargetException(e);
} finally{
pm.done();
}
}
private void executeChange(IProgressMonitor pm) throws CoreException {
Assert.isNotNull(fChangeContext);
IRewriteTarget[] targets= null;
try {
targets= getRewriteTargets();
beginCompoundChange(targets);
// Since we have done precondition checking this check should be fast. No PM.
// PR: 1GEWDUH: ITPJCORE:WINNT - Refactoring - Unable to undo refactor change
fChange.aboutToPerform(fChangeContext, new NullProgressMonitor());
IWorkspaceRunnable runnable= new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) throws CoreException {
try {
fChange.perform(fChangeContext, monitor);
} catch (ChangeAbortException e) {
throw new CoreException(
new Status(
IStatus.ERROR,
JavaPlugin.getPluginId(), IJavaStatusConstants.CHANGE_ABORTED,
RefactoringMessages.getString("PerformChangeOperation.unrecoverable_error"), e)); //$NON-NLS-1$
}
}
};
JavaCore.run(runnable, pm);
} finally {
fChange.performed();
if (targets != null)
endCompoundChange(targets);
}
}
private boolean createChange() {
return fCreateChangeOperation != null;
}
private static void beginCompoundChange(IRewriteTarget[] targets) {
for (int i= 0; i < targets.length; i++) {
targets[i].beginCompoundChange();
}
}
private static void endCompoundChange(IRewriteTarget[] targets) {
for (int i= 0; i < targets.length; i++) {
targets[i].endCompoundChange();
}
}
private static IRewriteTarget[] getRewriteTargets() {
IEditorPart[] editors= JavaPlugin.getInstanciatedEditors();
List result= new ArrayList(editors.length);
for (int i= 0; i < editors.length; i++) {
IRewriteTarget target= (IRewriteTarget)editors[i].getAdapter(IRewriteTarget.class);
if (target != null) {
result.add(target);
}
}
return (IRewriteTarget[]) result.toArray(new IRewriteTarget[result.size()]);
}
}