1 11 package org.eclipse.ltk.core.refactoring; 12 13 import java.util.ArrayList ; 14 import java.util.Arrays ; 15 import java.util.Collections ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 19 import org.eclipse.core.runtime.Assert; 20 import org.eclipse.core.runtime.CoreException; 21 import org.eclipse.core.runtime.IProgressMonitor; 22 import org.eclipse.core.runtime.ISafeRunnable; 23 import org.eclipse.core.runtime.OperationCanceledException; 24 import org.eclipse.core.runtime.SafeRunner; 25 import org.eclipse.core.runtime.SubProgressMonitor; 26 27 import org.eclipse.ltk.internal.core.refactoring.RefactoringCoreMessages; 28 import org.eclipse.ltk.internal.core.refactoring.RefactoringCorePlugin; 29 30 42 public class CompositeChange extends Change { 43 44 private String fName; 45 private List fChanges; 46 private boolean fIsSynthetic; 47 private Change fUndoUntilException; 48 49 55 public CompositeChange(String name) { 56 this(name, new ArrayList (2)); 57 } 58 59 67 public CompositeChange(String name, Change[] children) { 68 this(name, new ArrayList (children.length)); 69 addAll(children); 70 } 71 72 private CompositeChange(String name, List changes) { 73 Assert.isNotNull(name); 74 Assert.isNotNull(changes); 75 fName= name; 76 fChanges= changes; 77 } 78 79 85 public boolean isSynthetic() { 86 return fIsSynthetic; 87 } 88 89 92 public void markAsSynthetic() { 93 fIsSynthetic= true; 94 } 95 96 99 public String getName() { 100 return fName; 101 } 102 103 109 public void add(Change change) { 110 if (change != null) { 111 Assert.isTrue(change.getParent() == null); 112 fChanges.add(change); 113 change.setParent(this); 114 } 115 } 116 117 122 public void addAll(Change[] changes) { 123 for (int i= 0; i < changes.length; i++) { 124 add(changes[i]); 125 } 126 } 127 128 135 public void merge(CompositeChange change) { 136 Change[] others= change.getChildren(); 137 for (int i= 0; i < others.length; i++) { 138 Change other= others[i]; 139 change.remove(other); 140 add(other); 141 } 142 } 143 144 152 public boolean remove(Change change) { 153 Assert.isNotNull(change); 154 boolean result= fChanges.remove(change); 155 if (result) { 156 change.setParent(null); 157 } 158 return result; 159 160 } 161 162 170 public Change[] clear() { 171 Change[] result= (Change[])fChanges.toArray(new Change[fChanges.size()]); 172 fChanges.clear(); 173 return result; 174 } 175 176 182 public Change[] getChildren() { 183 return (Change[])fChanges.toArray(new Change[fChanges.size()]); 184 } 185 186 195 public void setEnabled(boolean enabled) { 196 super.setEnabled(enabled); 197 for (Iterator iter= fChanges.iterator(); iter.hasNext(); ) { 198 ((Change)iter.next()).setEnabled(enabled); 199 } 200 } 201 202 212 public void initializeValidationData(IProgressMonitor pm) { 213 pm.beginTask("", fChanges.size()); for (Iterator iter= fChanges.iterator(); iter.hasNext();) { 215 Change change= (Change)iter.next(); 216 change.initializeValidationData(new SubProgressMonitor(pm, 1)); 217 pm.worked(1); 218 } 219 } 220 221 233 public RefactoringStatus isValid(IProgressMonitor pm) throws CoreException { 234 RefactoringStatus result= new RefactoringStatus(); 235 pm.beginTask("", fChanges.size()); for (Iterator iter= fChanges.iterator(); iter.hasNext() && !result.hasFatalError();) { 237 Change change= (Change)iter.next(); 238 if (change.isEnabled()) 239 result.merge(change.isValid(new SubProgressMonitor(pm, 1))); 240 else 241 pm.worked(1); 242 if (pm.isCanceled()) 243 throw new OperationCanceledException(); 244 } 245 pm.done(); 246 return result; 247 } 248 249 262 public Change perform(IProgressMonitor pm) throws CoreException { 263 fUndoUntilException= null; 264 List undos= new ArrayList (fChanges.size()); 265 pm.beginTask("", fChanges.size()); pm.setTaskName(RefactoringCoreMessages.CompositeChange_performingChangesTask_name); 267 Change change= null; 268 boolean canceled= false; 269 try { 270 for (Iterator iter= fChanges.iterator(); iter.hasNext();) { 271 change= (Change)iter.next(); 272 if (canceled && !internalProcessOnCancel(change)) 273 continue; 274 275 if (change.isEnabled()) { 276 Change undoChange= null; 277 try { 278 undoChange= change.perform(new SubProgressMonitor(pm, 1)); 279 } catch(OperationCanceledException e) { 280 canceled= true; 281 if (!internalContinueOnCancel()) 282 throw e; 283 undos= null; 284 } 285 if (undos != null) { 286 if (undoChange == null) { 287 undos= null; 288 } else { 289 undos.add(undoChange); 290 } 291 } 292 } 293 iter.remove(); 298 final Change changeToDispose= change; 301 SafeRunner.run(new ISafeRunnable() { 302 public void run() throws Exception { 303 changeToDispose.dispose(); 304 } 305 public void handleException(Throwable exception) { 306 RefactoringCorePlugin.log(exception); 307 } 308 }); 309 } 310 if (canceled) 311 throw new OperationCanceledException(); 312 if (undos != null) { 313 Collections.reverse(undos); 314 return createUndoChange((Change[]) undos.toArray(new Change[undos.size()])); 315 } else { 316 return null; 317 } 318 } catch (CoreException e) { 319 handleUndos(change, undos); 320 internalHandleException(change, e); 321 throw e; 322 } catch (RuntimeException e) { 323 handleUndos(change, undos); 324 internalHandleException(change, e); 325 throw e; 326 } 327 } 328 329 private void handleUndos(Change failedChange, List undos) { 330 if (undos == null) { 331 fUndoUntilException= null; 332 return; 333 } 334 if (failedChange instanceof CompositeChange) { 335 Change partUndoChange= ((CompositeChange)failedChange).getUndoUntilException(); 336 if (partUndoChange != null) { 337 undos.add(partUndoChange); 338 } 339 } 340 if (undos.size() == 0) { 341 fUndoUntilException= new NullChange(getName()); 342 return; 343 } 344 Collections.reverse(undos); 345 fUndoUntilException= createUndoChange((Change[]) undos.toArray(new Change[undos.size()])); 346 } 347 348 359 protected void internalHandleException(Change change, Throwable t) { 360 } 362 363 377 protected boolean internalContinueOnCancel() { 378 return false; 379 } 380 381 396 protected boolean internalProcessOnCancel(Change change) { 397 return false; 398 } 399 400 407 public void dispose() { 408 for (Iterator iter= fChanges.iterator(); iter.hasNext(); ) { 409 final Change change= (Change)iter.next(); 410 SafeRunner.run(new ISafeRunnable() { 411 public void run() throws Exception { 412 change.dispose(); 413 } 414 public void handleException(Throwable exception) { 415 RefactoringCorePlugin.log(exception); 416 } 417 }); 418 } 419 } 420 421 431 public Change getUndoUntilException() { 432 return fUndoUntilException; 433 } 434 435 447 protected Change createUndoChange(Change[] childUndos) { 448 return new CompositeChange(getName(), childUndos); 449 } 450 451 454 public Object [] getAffectedObjects() { 455 if (fChanges.size() == 0) 456 return new Object [0]; 457 List result= new ArrayList (); 458 for (Iterator iter= fChanges.iterator(); iter.hasNext();) { 459 Change change= (Change)iter.next(); 460 Object [] affectedObjects= change.getAffectedObjects(); 461 if (affectedObjects == null) 462 return null; 463 result.addAll(Arrays.asList(affectedObjects)); 464 } 465 return result.toArray(); 466 } 467 468 471 public Object getModifiedElement() { 472 return null; 473 } 474 475 480 public ChangeDescriptor getDescriptor() { 481 for (final Iterator iterator= fChanges.iterator(); iterator.hasNext();) { 482 final Change change= (Change) iterator.next(); 483 final ChangeDescriptor descriptor= change.getDescriptor(); 484 if (descriptor != null) 485 return descriptor; 486 } 487 return null; 488 } 489 490 public String toString() { 491 StringBuffer buff= new StringBuffer (); 492 buff.append(getName()); 493 buff.append("\n"); for (Iterator iter= fChanges.iterator(); iter.hasNext();) { 495 buff.append("<").append(iter.next().toString()).append("/>\n"); } 497 return buff.toString(); 498 } 499 } 500 | Popular Tags |