/** * {@inheritDoc} * * <p>The composite change sends <code>isValid</code> to all its children until the first one * returns a status with a severity of <code>FATAL * </code>. If one of the children throws an exception the remaining children will not receive the * <code>isValid</code> call. * * <p>Client are allowed to extend this method. */ public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException { RefactoringStatus result = new RefactoringStatus(); pm.beginTask("", fChanges.size()); // $NON-NLS-1$ for (Iterator iter = fChanges.iterator(); iter.hasNext() && !result.hasFatalError(); ) { Change change = (Change) iter.next(); if (change.isEnabled()) result.merge(change.isValid(new SubProgressMonitor(pm, 1))); else pm.worked(1); if (pm.isCanceled()) throw new OperationCanceledException(); } pm.done(); return result; }
/** * {@inheritDoc} * * <p>The composite change sends <code>perform</code> to all its <em>enabled</em> children. If one * of the children throws an exception the remaining children will not receive the <code>perform * </code> call. In this case the method <code> * getUndoUntilException</code> can be used to get an undo object containing the undo objects of * all executed children. * * <p>Client are allowed to extend this method. */ public Change perform(IProgressMonitor pm) throws CoreException { fUndoUntilException = null; List undos = new ArrayList(fChanges.size()); pm.beginTask("", fChanges.size()); // $NON-NLS-1$ pm.setTaskName(RefactoringCoreMessages.CompositeChange_performingChangesTask_name); Change change = null; boolean canceled = false; try { for (Iterator iter = fChanges.iterator(); iter.hasNext(); ) { change = (Change) iter.next(); if (canceled && !internalProcessOnCancel(change)) continue; if (change.isEnabled()) { Change undoChange = null; try { undoChange = change.perform(new SubProgressMonitor(pm, 1)); } catch (OperationCanceledException e) { canceled = true; if (!internalContinueOnCancel()) throw e; undos = null; } if (undos != null) { if (undoChange == null) { undos = null; } else { undos.add(undoChange); } } } // remove the change from the list of children to give // the garbage collector the change to collect the change. This // ensures that the memory consumption doesn't go up when // producing the undo change tree. iter.remove(); // Make sure we dispose the change since it will now longer be // in the list of children when call CompositeChange#dispose() final Change changeToDispose = change; SafeRunner.run( new ISafeRunnable() { public void run() throws Exception { changeToDispose.dispose(); } public void handleException(Throwable exception) { RefactoringCorePlugin.log(exception); } }); } if (canceled) throw new OperationCanceledException(); if (undos != null) { Collections.reverse(undos); return createUndoChange((Change[]) undos.toArray(new Change[undos.size()])); } else { return null; } } catch (CoreException e) { handleUndos(change, undos); internalHandleException(change, e); throw e; } catch (RuntimeException e) { handleUndos(change, undos); internalHandleException(change, e); throw e; } }