1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
13 import java.io.InputStream;
14 import java.util.ArrayList;
15 import java.util.HashMap;
17 import net.sourceforge.phpdt.core.ICompilationUnit;
18 import net.sourceforge.phpdt.core.IJavaElement;
19 import net.sourceforge.phpdt.core.IJavaElementDelta;
20 import net.sourceforge.phpdt.core.IJavaModel;
21 import net.sourceforge.phpdt.core.IJavaModelStatus;
22 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
23 import net.sourceforge.phpdt.core.IPackageFragment;
24 import net.sourceforge.phpdt.core.IWorkingCopy;
25 import net.sourceforge.phpdt.core.JavaModelException;
26 import net.sourceforge.phpdt.internal.core.util.PerThreadObject;
27 import net.sourceforge.phpdt.internal.core.util.Util;
29 import org.eclipse.core.resources.IContainer;
30 import org.eclipse.core.resources.IFile;
31 import org.eclipse.core.resources.IFolder;
32 import org.eclipse.core.resources.IResource;
33 import org.eclipse.core.resources.IResourceStatus;
34 import org.eclipse.core.resources.IWorkspace;
35 import org.eclipse.core.resources.IWorkspaceRunnable;
36 import org.eclipse.core.resources.ResourcesPlugin;
37 import org.eclipse.core.runtime.CoreException;
38 import org.eclipse.core.runtime.IPath;
39 import org.eclipse.core.runtime.IProgressMonitor;
40 import org.eclipse.core.runtime.OperationCanceledException;
41 import org.eclipse.core.runtime.Path;
42 import org.eclipse.core.runtime.SubProgressMonitor;
43 import org.eclipse.core.runtime.jobs.ISchedulingRule;
46 * Defines behavior common to all Java Model operations
48 public abstract class JavaModelOperation implements IWorkspaceRunnable, IProgressMonitor {
49 protected interface IPostAction {
51 * Returns the id of this action.
53 * @see JavaModelOperation#postAction
60 void run() throws JavaModelException;
64 * Constants controlling the insertion mode of an action.
66 * @see JavaModelOperation#postAction
68 protected static final int APPEND = 1; // insert at the end
70 protected static final int REMOVEALL_APPEND = 2; // remove all existing ones with same ID, and add new one at the end
72 protected static final int KEEP_EXISTING = 3; // do not insert if already existing with same ID
75 * Whether tracing post actions is enabled.
77 protected static boolean POST_ACTION_VERBOSE;
80 * A list of IPostActions.
82 protected IPostAction[] actions;
84 protected int actionsStart = 0;
86 protected int actionsEnd = -1;
89 * A HashMap of attributes that can be used by operations
91 protected HashMap attributes;
93 public static final String HAS_MODIFIED_RESOURCE_ATTR = "hasModifiedResource"; //$NON-NLS-1$
95 public static final String TRUE = "true"; //$NON-NLS-1$
97 //public static final String FALSE = "false"; //$NON-NLS-1$
100 * The elements this operation operates on, or <code>null</code> if this operation does not operate on specific elements.
102 protected IJavaElement[] fElementsToProcess;
105 * The parent elements this operation operates with or <code>null</code> if this operation does not operate with specific parent
108 protected IJavaElement[] fParentElements;
111 * An empty collection of <code>IJavaElement</code> s - the common empty result if no elements are created, or if this operation
112 * is not actually executed.
114 protected static IJavaElement[] NO_ELEMENTS = new IJavaElement[] {};
117 * The elements created by this operation - empty until the operation actually creates elements.
119 protected IJavaElement[] resultElements = NO_ELEMENTS;
122 * The progress monitor passed into this operation
124 protected IProgressMonitor progressMonitor = null;
127 * A flag indicating whether this operation is nested.
129 protected boolean isNested = false;
132 * Conflict resolution policy - by default do not force (fail on a conflict).
134 protected boolean force = false;
137 * A per thread stack of java model operations (PerThreadObject of ArrayList).
139 protected static PerThreadObject operationStacks = new PerThreadObject();
141 protected JavaModelOperation() {
145 * A common constructor for all Java Model operations.
147 protected JavaModelOperation(IJavaElement[] elements) {
148 fElementsToProcess = elements;
152 * Common constructor for all Java Model operations.
154 protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements) {
155 fElementsToProcess = elementsToProcess;
156 fParentElements = parentElements;
160 * A common constructor for all Java Model operations.
162 protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) {
163 fElementsToProcess = elementsToProcess;
164 fParentElements = parentElements;
169 * A common constructor for all Java Model operations.
171 protected JavaModelOperation(IJavaElement[] elements, boolean force) {
172 fElementsToProcess = elements;
177 * Common constructor for all Java Model operations.
179 protected JavaModelOperation(IJavaElement element) {
180 fElementsToProcess = new IJavaElement[] { element };
184 * A common constructor for all Java Model operations.
186 protected JavaModelOperation(IJavaElement element, boolean force) {
187 fElementsToProcess = new IJavaElement[] { element };
192 * Registers the given action at the end of the list of actions to run.
194 protected void addAction(IPostAction action) {
195 int length = this.actions.length;
196 if (length == ++this.actionsEnd) {
197 System.arraycopy(this.actions, 0, this.actions = new IPostAction[length * 2], 0, length);
199 this.actions[this.actionsEnd] = action;
203 * Registers the given delta with the Java Model Manager.
205 protected void addDelta(IJavaElementDelta delta) {
206 JavaModelManager.getJavaModelManager().registerJavaModelDelta(delta);
210 * Registers the given reconcile delta with the Java Model Manager.
212 protected void addReconcileDelta(IWorkingCopy workingCopy, IJavaElementDelta delta) {
213 HashMap reconcileDeltas = JavaModelManager.getJavaModelManager().reconcileDeltas;
214 JavaElementDelta previousDelta = (JavaElementDelta) reconcileDeltas.get(workingCopy);
215 if (previousDelta != null) {
216 IJavaElementDelta[] children = delta.getAffectedChildren();
217 for (int i = 0, length = children.length; i < length; i++) {
218 JavaElementDelta child = (JavaElementDelta) children[i];
219 previousDelta.insertDeltaTree(child.getElement(), child);
222 reconcileDeltas.put(workingCopy, delta);
227 * Deregister the reconcile delta for the given working copy
229 protected void removeReconcileDelta(IWorkingCopy workingCopy) {
230 JavaModelManager.getJavaModelManager().reconcileDeltas.remove(workingCopy);
234 * @see IProgressMonitor
236 public void beginTask(String name, int totalWork) {
237 if (progressMonitor != null) {
238 progressMonitor.beginTask(name, totalWork);
243 * Checks with the progress monitor to see whether this operation should be canceled. An operation should regularly call this
244 * method during its operation so that the user can cancel it.
246 * @exception OperationCanceledException
247 * if cancelling the operation has been requested
248 * @see IProgressMonitor#isCanceled
250 protected void checkCanceled() {
252 throw new OperationCanceledException(Util.bind("operation.cancelled")); //$NON-NLS-1$
257 * Common code used to verify the elements this operation is processing.
259 * @see JavaModelOperation#verify()
261 protected IJavaModelStatus commonVerify() {
262 if (fElementsToProcess == null || fElementsToProcess.length == 0) {
263 return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
265 for (int i = 0; i < fElementsToProcess.length; i++) {
266 if (fElementsToProcess[i] == null) {
267 return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
270 return JavaModelStatus.VERIFIED_OK;
274 * Convenience method to copy resources
276 protected void copyResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
277 IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
278 IWorkspace workspace = resources[0].getWorkspace();
280 workspace.copy(resources, destinationPath, false, subProgressMonitor);
281 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
282 } catch (CoreException e) {
283 throw new JavaModelException(e);
288 * Convenience method to create a file
290 protected void createFile(IContainer folder, String name, InputStream contents, boolean force) throws JavaModelException {
291 IFile file = folder.getFile(new Path(name));
293 file.create(contents, force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, getSubProgressMonitor(1));
294 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
295 } catch (CoreException e) {
296 throw new JavaModelException(e);
301 * Convenience method to create a folder
303 protected void createFolder(IContainer parentFolder, String name, boolean force) throws JavaModelException {
304 IFolder folder = parentFolder.getFolder(new Path(name));
306 // we should use true to create the file locally. Only VCM should use tru/false
307 folder.create(force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, true, // local
308 getSubProgressMonitor(1));
309 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
310 } catch (CoreException e) {
311 throw new JavaModelException(e);
316 * Convenience method to delete an empty package fragment
318 protected void deleteEmptyPackageFragment(IPackageFragment fragment, boolean force, IResource rootResource)
319 throws JavaModelException {
321 IContainer resource = (IContainer) fragment.getResource();
324 resource.delete(force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, getSubProgressMonitor(1));
325 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
326 while (resource instanceof IFolder) {
327 // deleting a package: delete the parent if it is empty (eg. deleting x.y where folder x doesn't have resources but y)
328 // without deleting the package fragment root
329 resource = resource.getParent();
330 if (!resource.equals(rootResource) && resource.members().length == 0) {
331 resource.delete(force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, getSubProgressMonitor(1));
332 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
335 } catch (CoreException e) {
336 throw new JavaModelException(e);
341 * Convenience method to delete a resource
343 protected void deleteResource(IResource resource, int flags) throws JavaModelException {
345 resource.delete(flags, getSubProgressMonitor(1));
346 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
347 } catch (CoreException e) {
348 throw new JavaModelException(e);
353 * Convenience method to delete resources
355 protected void deleteResources(IResource[] resources, boolean force) throws JavaModelException {
356 if (resources == null || resources.length == 0)
358 IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
359 IWorkspace workspace = resources[0].getWorkspace();
361 workspace.delete(resources, force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, subProgressMonitor);
362 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
363 } catch (CoreException e) {
364 throw new JavaModelException(e);
369 * @see IProgressMonitor
372 if (progressMonitor != null) {
373 progressMonitor.done();
378 * Returns whether the given path is equals to one of the given other paths.
380 protected boolean equalsOneOf(IPath path, IPath[] otherPaths) {
381 for (int i = 0, length = otherPaths.length; i < length; i++) {
382 if (path.equals(otherPaths[i])) {
390 * Verifies the operation can proceed and executes the operation. Subclasses should override <code>#verify</code> and
391 * <code>executeOperation</code> to implement the specific operation behavior.
393 * @exception JavaModelException
394 * The operation has failed.
396 // protected void execute() throws JavaModelException {
397 // IJavaModelStatus status= verify();
398 // if (status.isOK()) {
399 // // if first time here, computes the root infos before executing the operation
400 // DeltaProcessor deltaProcessor = JavaModelManager.getJavaModelManager().deltaProcessor;
401 // if (deltaProcessor.roots == null) {
402 // deltaProcessor.initializeRoots();
404 // executeOperation();
406 // throw new JavaModelException(status);
410 * Convenience method to run an operation within this operation
412 public void executeNestedOperation(JavaModelOperation operation, int subWorkAmount) throws JavaModelException {
413 IProgressMonitor subProgressMonitor = getSubProgressMonitor(subWorkAmount);
414 // fix for 1FW7IKC, part (1)
416 operation.setNested(true);
417 operation.run(subProgressMonitor);
418 } catch (CoreException ce) {
419 if (ce instanceof JavaModelException) {
420 throw (JavaModelException) ce;
422 // translate the core exception to a java model exception
423 if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
424 Throwable e = ce.getStatus().getException();
425 if (e instanceof JavaModelException) {
426 throw (JavaModelException) e;
429 throw new JavaModelException(ce);
435 * Performs the operation specific behavior. Subclasses must override.
437 protected abstract void executeOperation() throws JavaModelException;
440 * Returns the attribute registered at the given key with the top level operation. Returns null if no such attribute is found.
442 protected Object getAttribute(Object key) {
443 ArrayList stack = this.getCurrentOperationStack();
444 if (stack.size() == 0)
446 JavaModelOperation topLevelOp = (JavaModelOperation) stack.get(0);
447 if (topLevelOp.attributes == null) {
450 return topLevelOp.attributes.get(key);
455 * Returns the compilation unit the given element is contained in, or the element itself (if it is a compilation unit), otherwise
458 protected ICompilationUnit getCompilationUnitFor(IJavaElement element) {
460 return ((JavaElement) element).getCompilationUnit();
464 * Returns the stack of operations running in the current thread. Returns an empty stack if no operations are currently running in
467 protected ArrayList getCurrentOperationStack() {
468 ArrayList stack = (ArrayList) operationStacks.getCurrent();
470 stack = new ArrayList();
471 operationStacks.setCurrent(stack);
477 * Returns the elements to which this operation applies, or <code>null</code> if not applicable.
479 protected IJavaElement[] getElementsToProcess() {
480 return fElementsToProcess;
484 * Returns the element to which this operation applies, or <code>null</code> if not applicable.
486 protected IJavaElement getElementToProcess() {
487 if (fElementsToProcess == null || fElementsToProcess.length == 0) {
490 return fElementsToProcess[0];
494 * Returns the Java Model this operation is operating in.
496 public IJavaModel getJavaModel() {
497 if (fElementsToProcess == null || fElementsToProcess.length == 0) {
498 return getParentElement().getJavaModel();
500 return fElementsToProcess[0].getJavaModel();
504 // protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException {
505 // IPath rootPath = root.getPath();
506 // IClasspathEntry[] classpath = root.getJavaProject().getRawClasspath();
507 // int length = classpath.length;
508 // IPath[] result = new IPath[length];
510 // for (int i = 0; i < length; i++) {
511 // IPath path = classpath[i].getPath();
512 // if (rootPath.isPrefixOf(path) && !rootPath.equals(path)) {
513 // result[index++] = path;
516 // if (index < length) {
517 // System.arraycopy(result, 0, result = new IPath[index], 0, index);
522 * Returns the parent element to which this operation applies, or <code>null</code> if not applicable.
524 protected IJavaElement getParentElement() {
525 if (fParentElements == null || fParentElements.length == 0) {
528 return fParentElements[0];
532 * Returns the parent elements to which this operation applies, or <code>null</code> if not applicable.
534 protected IJavaElement[] getParentElements() {
535 return fParentElements;
539 * Returns the elements created by this operation.
541 public IJavaElement[] getResultElements() {
542 return resultElements;
546 * Returns the scheduling rule for this operation (i.e. the resource that needs to be locked while this operation is running.
547 * Subclasses can override.
549 protected ISchedulingRule getSchedulingRule() {
550 return ResourcesPlugin.getWorkspace().getRoot();
554 * Creates and returns a subprogress monitor if appropriate.
556 protected IProgressMonitor getSubProgressMonitor(int workAmount) {
557 IProgressMonitor sub = null;
558 if (progressMonitor != null) {
559 sub = new SubProgressMonitor(progressMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
565 * Returns whether this operation has performed any resource modifications. Returns false if this operation has not been executed
568 public boolean hasModifiedResource() {
569 return !this.isReadOnly() && this.getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE;
572 public void internalWorked(double work) {
573 if (progressMonitor != null) {
574 progressMonitor.internalWorked(work);
579 * @see IProgressMonitor
581 public boolean isCanceled() {
582 if (progressMonitor != null) {
583 return progressMonitor.isCanceled();
589 * Returns <code>true</code> if this operation performs no resource modifications, otherwise <code>false</code>. Subclasses
592 public boolean isReadOnly() {
597 * Returns whether this operation is the first operation to run in the current thread.
599 protected boolean isTopLevelOperation() {
601 return (stack = this.getCurrentOperationStack()).size() > 0 && stack.get(0) == this;
605 * Returns the index of the first registered action with the given id, starting from a given position. Returns -1 if not found.
607 protected int firstActionWithID(String id, int start) {
608 for (int i = start; i <= this.actionsEnd; i++) {
609 if (this.actions[i].getID().equals(id)) {
617 * Convenience method to move resources
619 protected void moveResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
620 IProgressMonitor subProgressMonitor = null;
621 if (progressMonitor != null) {
622 subProgressMonitor = new SubProgressMonitor(progressMonitor, resources.length,
623 SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
625 IWorkspace workspace = resources[0].getWorkspace();
627 workspace.move(resources, destinationPath, false, subProgressMonitor);
628 this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
629 } catch (CoreException e) {
630 throw new JavaModelException(e);
635 * Creates and returns a new <code>IJavaElementDelta</code> on the Java Model.
637 public JavaElementDelta newJavaElementDelta() {
638 return new JavaElementDelta(getJavaModel());
642 * Removes the last pushed operation from the stack of running operations. Returns the poped operation or null if the stack was
645 protected JavaModelOperation popOperation() {
646 ArrayList stack = getCurrentOperationStack();
647 int size = stack.size();
649 if (size == 1) { // top level operation
650 operationStacks.setCurrent(null); // release reference (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33927)
652 return (JavaModelOperation) stack.remove(size - 1);
659 * Registers the given action to be run when the outer most java model operation has finished. The insertion mode controls
660 * whether: - the action should discard all existing actions with the same id, and be queued at the end (REMOVEALL_APPEND), - the
661 * action should be ignored if there is already an action with the same id (KEEP_EXISTING), - the action should be queued at the
662 * end without looking at existing actions (APPEND)
664 protected void postAction(IPostAction action, int insertionMode) {
665 if (POST_ACTION_VERBOSE) {
667 .print("(" + Thread.currentThread() + ") [JavaModelOperation.postAction(IPostAction, int)] Posting action " + action.getID()); //$NON-NLS-1$ //$NON-NLS-2$
668 switch (insertionMode) {
669 case REMOVEALL_APPEND:
670 System.out.println(" (REMOVEALL_APPEND)"); //$NON-NLS-1$
673 System.out.println(" (KEEP_EXISTING)"); //$NON-NLS-1$
676 System.out.println(" (APPEND)"); //$NON-NLS-1$
681 JavaModelOperation topLevelOp = (JavaModelOperation) getCurrentOperationStack().get(0);
682 IPostAction[] postActions = topLevelOp.actions;
683 if (postActions == null) {
684 topLevelOp.actions = postActions = new IPostAction[1];
685 postActions[0] = action;
686 topLevelOp.actionsEnd = 0;
688 String id = action.getID();
689 switch (insertionMode) {
690 case REMOVEALL_APPEND:
691 int index = this.actionsStart - 1;
692 while ((index = topLevelOp.firstActionWithID(id, index + 1)) >= 0) {
693 // remove action[index]
694 System.arraycopy(postActions, index + 1, postActions, index, topLevelOp.actionsEnd - index);
695 postActions[topLevelOp.actionsEnd--] = null;
697 topLevelOp.addAction(action);
700 if (topLevelOp.firstActionWithID(id, 0) < 0) {
701 topLevelOp.addAction(action);
705 topLevelOp.addAction(action);
712 * Returns whether the given path is the prefix of one of the given other paths.
714 protected boolean prefixesOneOf(IPath path, IPath[] otherPaths) {
715 for (int i = 0, length = otherPaths.length; i < length; i++) {
716 if (path.isPrefixOf(otherPaths[i])) {
724 * Pushes the given operation on the stack of operations currently running in this thread.
726 protected void pushOperation(JavaModelOperation operation) {
727 getCurrentOperationStack().add(operation);
731 * Main entry point for Java Model operations. Executes this operation and registers any deltas created.
733 * @see IWorkspaceRunnable
734 * @exception CoreException
735 * if the operation fails
737 public void run(IProgressMonitor monitor) throws CoreException {
738 JavaModelManager manager = JavaModelManager.getJavaModelManager();
739 DeltaProcessor deltaProcessor = manager.getDeltaProcessor();
740 int previousDeltaCount = deltaProcessor.javaModelDeltas.size();
742 progressMonitor = monitor;
745 // computes the root infos before executing the operation
746 // noop if aready initialized
747 JavaModelManager.getJavaModelManager().deltaState.initializeRoots();
751 if (this.isTopLevelOperation()) {
752 this.runPostActions();
758 // TODO jsurfer temp-del
759 // update JavaModel using deltas that were recorded during this operation
760 // for (int i = previousDeltaCount, size = manager.javaModelDeltas.size(); i < size; i++) {
761 // manager.updateJavaModel((IJavaElementDelta)manager.javaModelDeltas.get(i));
765 // - the operation is a top level operation
766 // - the operation did produce some delta(s)
767 // - but the operation has not modified any resource
768 if (this.isTopLevelOperation()) {
769 if ((manager.javaModelDeltas.size() > previousDeltaCount || !manager.reconcileDeltas.isEmpty())
770 && !this.hasModifiedResource()) {
771 manager.fire(null, JavaModelManager.DEFAULT_CHANGE_EVENT);
772 } // else deltas are fired while processing the resource delta
781 * Main entry point for Java Model operations. Runs a Java Model Operation as an IWorkspaceRunnable if not read-only.
783 public void runOperation(IProgressMonitor monitor) throws JavaModelException {
784 IJavaModelStatus status = verify();
785 if (!status.isOK()) {
786 throw new JavaModelException(status);
792 // Use IWorkspace.run(...) to ensure that a build will be done in autobuild mode.
793 // Note that if the tree is locked, this will throw a CoreException, but this is ok
794 // as this operation is modifying the tree (not read-only) and a CoreException will be thrown anyway.
795 ResourcesPlugin.getWorkspace().run(this, getSchedulingRule(), IWorkspace.AVOID_UPDATE, monitor);
797 } catch (CoreException ce) {
798 if (ce instanceof JavaModelException) {
799 throw (JavaModelException) ce;
801 if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
802 Throwable e = ce.getStatus().getException();
803 if (e instanceof JavaModelException) {
804 throw (JavaModelException) e;
807 throw new JavaModelException(ce);
812 protected void runPostActions() throws JavaModelException {
813 while (this.actionsStart <= this.actionsEnd) {
814 IPostAction postAction = this.actions[this.actionsStart++];
815 if (POST_ACTION_VERBOSE) {
817 .println("(" + Thread.currentThread() + ") [JavaModelOperation.runPostActions()] Running action " + postAction.getID()); //$NON-NLS-1$ //$NON-NLS-2$
824 * Registers the given attribute at the given key with the top level operation.
826 protected void setAttribute(Object key, Object attribute) {
827 JavaModelOperation topLevelOp = (JavaModelOperation) this.getCurrentOperationStack().get(0);
828 if (topLevelOp.attributes == null) {
829 topLevelOp.attributes = new HashMap();
831 topLevelOp.attributes.put(key, attribute);
835 * @see IProgressMonitor
837 public void setCanceled(boolean b) {
838 if (progressMonitor != null) {
839 progressMonitor.setCanceled(b);
844 * Sets whether this operation is nested or not.
846 * @see CreateElementInCUOperation#checkCanceled
848 protected void setNested(boolean nested) {
853 * @see IProgressMonitor
855 public void setTaskName(String name) {
856 if (progressMonitor != null) {
857 progressMonitor.setTaskName(name);
862 * @see IProgressMonitor
864 public void subTask(String name) {
865 if (progressMonitor != null) {
866 progressMonitor.subTask(name);
871 * Returns a status indicating if there is any known reason this operation will fail. Operations are verified before they are run.
873 * Subclasses must override if they have any conditions to verify before this operation executes.
875 * @see IJavaModelStatus
877 protected IJavaModelStatus verify() {
878 return commonVerify();
882 * @see IProgressMonitor
884 public void worked(int work) {
885 if (progressMonitor != null) {
886 progressMonitor.worked(work);