Added new Option "Wrap PHPdocs and comments at print margin"
authoraxelcl <axelcl>
Mon, 17 Jan 2005 21:22:32 +0000 (21:22 +0000)
committeraxelcl <axelcl>
Mon, 17 Jan 2005 21:22:32 +0000 (21:22 +0000)
(disabled by default).

13 files changed:
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/DeltaProcessor.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModel.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/JavaModelOperation.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTableViewer.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTreeViewer.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ResourceToItemsMapper.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/IContextMenuConstants.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/ITypeHierarchyViewPart.java [new file with mode: 0644]
net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/JavaUI.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/PHPeclipsePlugin.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/phpeditor/PHPUnitEditor.java
net.sourceforge.phpeclipse/src/net/sourceforge/phpeclipse/wizards/PHPWizardMessages.java

index a0bf965..41d5e07 100644 (file)
@@ -2666,6 +2666,7 @@ public class DeltaProcessor implements IResourceChangeListener {
 //                     }
 //     }
 //}
+       
 /**
  * Upadtes the index of the given root (assuming it's an addition or a removal).
  * This is done recusively, pkg being the current package.
index d24e00b..489e3c6 100644 (file)
@@ -503,7 +503,8 @@ protected void runOperation(MultiOperation op, IJavaElement[] elements, IJavaEle
                        op.setInsertBefore(elements[i], siblings[i]);
                }
        }
-       runOperation(op, monitor);
+//     runOperation(op, monitor);
+       op.runOperation(monitor);
 }
 /**
  * @private Debugging purposes
index 01d7c40..3410fbc 100644 (file)
@@ -38,13 +38,17 @@ import net.sourceforge.phpdt.core.IJavaModel;
 import net.sourceforge.phpdt.core.IJavaProject;
 import net.sourceforge.phpdt.core.IPackageFragment;
 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.IProblemRequestor;
 import net.sourceforge.phpdt.core.IWorkingCopy;
-import net.sourceforge.phpdt.core.JavaModelException;
 import net.sourceforge.phpdt.core.JavaCore;
-import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
-import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import net.sourceforge.phpdt.core.compiler.IProblem;
 import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
 import net.sourceforge.phpdt.internal.core.util.Util;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -68,23 +72,7 @@ import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Plugin;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.core.runtime.Status;
-
-import net.sourceforge.phpdt.internal.core.DefaultWorkingCopyOwner;
-
-import net.sourceforge.phpdt.internal.core.DeltaProcessingState;
-
-import net.sourceforge.phpdt.internal.core.DeltaProcessor;
-
-import net.sourceforge.phpdt.core.IParent;
-import net.sourceforge.phpdt.internal.core.JavaElementInfo;
-
-import net.sourceforge.phpdt.core.IProblemRequestor;
-import net.sourceforge.phpdt.core.WorkingCopyOwner;
-import net.sourceforge.phpdt.core.compiler.IProblem;
-import net.sourceforge.phpdt.internal.core.CompilationUnit;
-import net.sourceforge.phpdt.internal.core.JavaElement;
-import net.sourceforge.phpdt.internal.core.JavaElementDeltaBuilder;
-import net.sourceforge.phpdt.internal.core.JavaModelManager.PerWorkingCopyInfo;
+import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
 
 /**
  * The <code>JavaModelManager</code> manages instances of <code>IJavaModel</code>.
index f33c7a9..2d18786 100644 (file)
@@ -42,815 +42,849 @@ import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
 
-
 /**
  * Defines behavior common to all Java Model operations
  */
 public abstract class JavaModelOperation implements IWorkspaceRunnable, IProgressMonitor {
-       protected interface IPostAction {
-               /*
-                * Returns the id of this action.
-                * @see JavaModelOperation#postAction
-                */
-               String getID();
-               /*
-                * Run this action.
-                */
-               void run() throws JavaModelException;
-       }
-       /*
-        * Constants controlling the insertion mode of an action.
-        * @see JavaModelOperation#postAction
-        */
-       protected static final int APPEND = 1; // insert at the end
-       protected static final int REMOVEALL_APPEND = 2; // remove all existing ones with same ID, and add new one at the end
-       protected static final int KEEP_EXISTING = 3; // do not insert if already existing with same ID
-       
-       /*
-        * Whether tracing post actions is enabled.
-        */
-       protected static boolean POST_ACTION_VERBOSE;
-
-       /*
-        * A list of IPostActions.
-        */
-       protected IPostAction[] actions;
-       protected int actionsStart = 0;
-       protected int actionsEnd = -1;
-       /*
-        * A HashMap of attributes that can be used by operations
-        */
-       protected HashMap attributes;
-
-       public static final String HAS_MODIFIED_RESOURCE_ATTR = "hasModifiedResource"; //$NON-NLS-1$
-       public static final String TRUE = "true"; //$NON-NLS-1$
-       //public static final String FALSE = "false"; //$NON-NLS-1$
-               
-       /**
-        * The elements this operation operates on,
-        * or <code>null</code> if this operation
-        * does not operate on specific elements.
-        */
-       protected IJavaElement[] fElementsToProcess;
-       /**
-        * The parent elements this operation operates with
-        * or <code>null</code> if this operation
-        * does not operate with specific parent elements.
-        */
-       protected IJavaElement[] fParentElements;
-       /**
-        * An empty collection of <code>IJavaElement</code>s - the common
-        * empty result if no elements are created, or if this
-        * operation is not actually executed.
-        */
-       protected static IJavaElement[] NO_ELEMENTS= new IJavaElement[] {};
-
-
-       /**
-        * The elements created by this operation - empty
-        * until the operation actually creates elements.
-        */
-       protected IJavaElement[] resultElements= NO_ELEMENTS;
-
-       /**
-        * The progress monitor passed into this operation
-        */
-       protected IProgressMonitor progressMonitor= null;
-       /**
-        * A flag indicating whether this operation is nested.
-        */
-       protected boolean isNested = false;
-       /**
-        * Conflict resolution policy - by default do not force (fail on a conflict).
-        */
-       protected boolean force= false;
-
-       /*
-        * A per thread stack of java model operations (PerThreadObject of ArrayList).
-        */
-       protected static PerThreadObject operationStacks = new PerThreadObject();
-       protected JavaModelOperation() {
-       }
-       /**
-        * A common constructor for all Java Model operations.
-        */
-       protected JavaModelOperation(IJavaElement[] elements) {
-               fElementsToProcess = elements;
-       }
-       /**
-        * Common constructor for all Java Model operations.
-        */
-       protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements) {
-               fElementsToProcess = elementsToProcess;
-               fParentElements= parentElements;
-       }
-       /**
-        * A common constructor for all Java Model operations.
-        */
-       protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) {
-               fElementsToProcess = elementsToProcess;
-               fParentElements= parentElements;
-               this.force= force;
-       }
-       /**
-        * A common constructor for all Java Model operations.
-        */
-       protected JavaModelOperation(IJavaElement[] elements, boolean force) {
-               fElementsToProcess = elements;
-               this.force= force;
-       }
-       
-       /**
-        * Common constructor for all Java Model operations.
-        */
-       protected JavaModelOperation(IJavaElement element) {
-               fElementsToProcess = new IJavaElement[]{element};
-       }
-       /**
-        * A common constructor for all Java Model operations.
-        */
-       protected JavaModelOperation(IJavaElement element, boolean force) {
-               fElementsToProcess = new IJavaElement[]{element};
-               this.force= force;
-       }
-       
-       /*
-        * Registers the given action at the end of the list of actions to run.
-        */
-       protected void addAction(IPostAction action) {
-               int length = this.actions.length;
-               if (length == ++this.actionsEnd) {
-                       System.arraycopy(this.actions, 0, this.actions = new IPostAction[length*2], 0, length);
-               }
-               this.actions[this.actionsEnd] = action;
-       }
-       /*
-        * Registers the given delta with the Java Model Manager.
-        */
-       protected void addDelta(IJavaElementDelta delta) {
-               JavaModelManager.getJavaModelManager().registerJavaModelDelta(delta);
-       }
-       /*
-        * Registers the given reconcile delta with the Java Model Manager.
-        */
-       protected void addReconcileDelta(IWorkingCopy workingCopy, IJavaElementDelta delta) {
-               HashMap reconcileDeltas = JavaModelManager.getJavaModelManager().reconcileDeltas;
-               JavaElementDelta previousDelta = (JavaElementDelta)reconcileDeltas.get(workingCopy);
-               if (previousDelta != null) {
-                       IJavaElementDelta[] children = delta.getAffectedChildren();
-                       for (int i = 0, length = children.length; i < length; i++) {
-                               JavaElementDelta child = (JavaElementDelta)children[i];
-                               previousDelta.insertDeltaTree(child.getElement(), child);
-                       }
-               } else {
-                       reconcileDeltas.put(workingCopy, delta);
-               }
-       }
-       /*
-        * Deregister the reconcile delta for the given working copy
-        */
-       protected void removeReconcileDelta(IWorkingCopy workingCopy) {
-               JavaModelManager.getJavaModelManager().reconcileDeltas.remove(workingCopy);             
-       }
-       /**
-        * @see IProgressMonitor
-        */
-       public void beginTask(String name, int totalWork) {
-               if (progressMonitor != null) {
-                       progressMonitor.beginTask(name, totalWork);
-               }
-       }
-       /**
-        * Checks with the progress monitor to see whether this operation
-        * should be canceled. An operation should regularly call this method
-        * during its operation so that the user can cancel it.
-        *
-        * @exception OperationCanceledException if cancelling the operation has been requested
-        * @see IProgressMonitor#isCanceled
-        */
-       protected void checkCanceled() {
-               if (isCanceled()) {
-                       throw new OperationCanceledException(Util.bind("operation.cancelled")); //$NON-NLS-1$
-               }
-       }
-       /**
-        * Common code used to verify the elements this operation is processing.
-        * @see JavaModelOperation#verify()
-        */
-       protected IJavaModelStatus commonVerify() {
-               if (fElementsToProcess == null || fElementsToProcess.length == 0) {
-                       return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
-               }
-               for (int i = 0; i < fElementsToProcess.length; i++) {
-                       if (fElementsToProcess[i] == null) {
-                               return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
-                       }
-               }
-               return JavaModelStatus.VERIFIED_OK;
-       }
-       /**
-        * Convenience method to copy resources
-        */
-       protected void copyResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
-               IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
-               IWorkspace workspace = resources[0].getWorkspace();
-               try {
-                       workspace.copy(resources, destinationPath, false, subProgressMonitor);
-                       this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * Convenience method to create a file
-        */
-       protected void createFile(IContainer folder, String name, InputStream contents, boolean force) throws JavaModelException {
-               IFile file= folder.getFile(new Path(name));
-               try {
-                       file.create(
-                               contents, 
-                               force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
-                               getSubProgressMonitor(1));
-                               this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * Convenience method to create a folder
-        */
-       protected void createFolder(IContainer parentFolder, String name, boolean force) throws JavaModelException {
-               IFolder folder= parentFolder.getFolder(new Path(name));
-               try {
-                       // we should use true to create the file locally. Only VCM should use tru/false
-                       folder.create(
-                               force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
-                               true, // local
-                               getSubProgressMonitor(1));
-                               this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * Convenience method to delete an empty package fragment
-        */
-       protected void deleteEmptyPackageFragment(
-               IPackageFragment fragment,
-               boolean force,
-               IResource rootResource)
-               throws JavaModelException {
-       
-               IContainer resource = (IContainer) fragment.getResource();
-       
-               try {
-                       resource.delete(
-                               force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
-                               getSubProgressMonitor(1));
-                       this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-                       while (resource instanceof IFolder) {
-                               // deleting a package: delete the parent if it is empty (eg. deleting x.y where folder x doesn't have resources but y)
-                               // without deleting the package fragment root
-                               resource = resource.getParent();
-                               if (!resource.equals(rootResource) && resource.members().length == 0) {
-                                       resource.delete(
-                                               force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
-                                               getSubProgressMonitor(1));
-                                       this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-                               }
-                       }
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * Convenience method to delete a resource
-        */
-       protected void deleteResource(IResource resource,int flags) throws JavaModelException {
-               try {
-                       resource.delete(flags, getSubProgressMonitor(1));
-                       this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * Convenience method to delete resources
-        */
-       protected void deleteResources(IResource[] resources, boolean force) throws JavaModelException {
-               if (resources == null || resources.length == 0) return;
-               IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
-               IWorkspace workspace = resources[0].getWorkspace();
-               try {
-                       workspace.delete(
-                               resources,
-                               force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
-                               subProgressMonitor);
-                               this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * @see IProgressMonitor
-        */
-       public void done() {
-               if (progressMonitor != null) {
-                       progressMonitor.done();
-               }
-       }
-       /*
-        * Returns whether the given path is equals to one of the given other paths.
-        */
-       protected boolean equalsOneOf(IPath path, IPath[] otherPaths) {
-               for (int i = 0, length = otherPaths.length; i < length; i++) {
-                       if (path.equals(otherPaths[i])) {
-                               return true;
-                       }
-               }
-               return false;
-       }
-       /**
-        * Verifies the operation can proceed and executes the operation.
-        * Subclasses should override <code>#verify</code> and
-        * <code>executeOperation</code> to implement the specific operation behavior.
-        *
-        * @exception JavaModelException The operation has failed.
-        */
-//     protected void execute() throws JavaModelException {
-//             IJavaModelStatus status= verify();
-//             if (status.isOK()) {
-//                     // if first time here, computes the root infos before executing the operation
-//                     DeltaProcessor deltaProcessor = JavaModelManager.getJavaModelManager().deltaProcessor;
-//                     if (deltaProcessor.roots == null) {
-//                       deltaProcessor.initializeRoots();
-//                     }
-//                     executeOperation();
-//             } else {
-//                     throw new JavaModelException(status);
-//             }
-//     }
-       
-       /**
-        * Convenience method to run an operation within this operation
-        */
-       public void executeNestedOperation(JavaModelOperation operation, int subWorkAmount) throws JavaModelException {
-               IProgressMonitor subProgressMonitor = getSubProgressMonitor(subWorkAmount);
-               // fix for 1FW7IKC, part (1)
-               try {
-                       operation.setNested(true);
-                       operation.run(subProgressMonitor);
-               } catch (CoreException ce) {
-                       if (ce instanceof JavaModelException) {
-                               throw (JavaModelException)ce;
-                       } else {
-                               // translate the core exception to a java model exception
-                               if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
-                                       Throwable e = ce.getStatus().getException();
-                                       if (e instanceof JavaModelException) {
-                                               throw (JavaModelException) e;
-                                       }
-                               }
-                               throw new JavaModelException(ce);
-                       }
-               }
-       }
-       /**
-        * Performs the operation specific behavior. Subclasses must override.
-        */
-       protected abstract void executeOperation() throws JavaModelException;
-       /*
-        * Returns the attribute registered at the given key with the top level operation.
-        * Returns null if no such attribute is found.
-        */
-       protected Object getAttribute(Object key) {
-               ArrayList stack = this.getCurrentOperationStack();
-               if (stack.size() == 0) return null;
-               JavaModelOperation topLevelOp = (JavaModelOperation)stack.get(0);
-               if (topLevelOp.attributes == null) {
-                       return null;
-               } else {
-                       return topLevelOp.attributes.get(key);
-               }
-       }
-       /**
-        * Returns the compilation unit the given element is contained in,
-        * or the element itself (if it is a compilation unit),
-        * otherwise <code>null</code>.
-        */
-       protected ICompilationUnit getCompilationUnitFor(IJavaElement element) {
-       
-               return ((JavaElement)element).getCompilationUnit();
-       }
-       /*
-        * Returns the stack of operations running in the current thread.
-        * Returns an empty stack if no operations are currently running in this thread. 
-        */
-       protected ArrayList getCurrentOperationStack() {
-               ArrayList stack = (ArrayList)operationStacks.getCurrent();
-               if (stack == null) {
-                       stack = new ArrayList();
-                       operationStacks.setCurrent(stack);
-               }
-               return stack;
-       }
-       /**
-        * Returns the elements to which this operation applies,
-        * or <code>null</code> if not applicable.
-        */
-       protected IJavaElement[] getElementsToProcess() {
-               return fElementsToProcess;
-       }
-       /**
-        * Returns the element to which this operation applies,
-        * or <code>null</code> if not applicable.
-        */
-       protected IJavaElement getElementToProcess() {
-               if (fElementsToProcess == null || fElementsToProcess.length == 0) {
-                       return null;
-               }
-               return fElementsToProcess[0];
-       }
-       /**
-        * Returns the Java Model this operation is operating in.
-        */
-       public IJavaModel getJavaModel() {
-               if (fElementsToProcess == null || fElementsToProcess.length == 0) {
-                       return getParentElement().getJavaModel();
-               } else {
-                       return fElementsToProcess[0].getJavaModel();
-               }
-       }
-//     protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException {
-//             IPath rootPath = root.getPath();
-//             IClasspathEntry[] classpath = root.getJavaProject().getRawClasspath();
-//             int length = classpath.length;
-//             IPath[] result = new IPath[length];
-//             int index = 0;
-//             for (int i = 0; i < length; i++) {
-//                     IPath path = classpath[i].getPath();
-//                     if (rootPath.isPrefixOf(path) && !rootPath.equals(path)) {
-//                             result[index++] = path;
-//                     }
-//             }
-//             if (index < length) {
-//                     System.arraycopy(result, 0, result = new IPath[index], 0, index);
-//             }
-//             return result;
-//     }
-       /**
-        * Returns the parent element to which this operation applies,
-        * or <code>null</code> if not applicable.
-        */
-       protected IJavaElement getParentElement() {
-               if (fParentElements == null || fParentElements.length == 0) {
-                       return null;
-               }
-               return fParentElements[0];
-       }
-       /**
-        * Returns the parent elements to which this operation applies,
-        * or <code>null</code> if not applicable.
-        */
-       protected IJavaElement[] getParentElements() {
-               return fParentElements;
-       }
-       /**
-        * Returns the elements created by this operation.
-        */
-       public IJavaElement[] getResultElements() {
-               return resultElements;
-       }
-       /*
-        * Returns the scheduling rule for this operation (i.e. the resource that needs to be locked 
-        * while this operation is running.
-        * Subclasses can override.
-        */
-       protected ISchedulingRule getSchedulingRule() {
-               return ResourcesPlugin.getWorkspace().getRoot();
-       }
-       /**
-        * Creates and returns a subprogress monitor if appropriate.
-        */
-       protected IProgressMonitor getSubProgressMonitor(int workAmount) {
-               IProgressMonitor sub = null;
-               if (progressMonitor != null) {
-                       sub = new SubProgressMonitor(progressMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
-               }
-               return sub;
-       }
-
-       /**
-        * Returns whether this operation has performed any resource modifications.
-        * Returns false if this operation has not been executed yet.
-        */
-       public boolean hasModifiedResource() {
-               return !this.isReadOnly() && this.getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE; 
-       }
-       public void internalWorked(double work) {
-               if (progressMonitor != null) {
-                       progressMonitor.internalWorked(work);
-               }
-       }
-       /**
-        * @see IProgressMonitor
-        */
-       public boolean isCanceled() {
-               if (progressMonitor != null) {
-                       return progressMonitor.isCanceled();
-               }
-               return false;
-       }
-       /**
-        * Returns <code>true</code> if this operation performs no resource modifications,
-        * otherwise <code>false</code>. Subclasses must override.
-        */
-       public boolean isReadOnly() {
-               return false;
-       }
-       /*
-        * Returns whether this operation is the first operation to run in the current thread.
-        */
-       protected boolean isTopLevelOperation() {
-               ArrayList stack;
-               return 
-                       (stack = this.getCurrentOperationStack()).size() > 0
-                       && stack.get(0) == this;
-       }
-       /*
-        * Returns the index of the first registered action with the given id, starting from a given position.
-        * Returns -1 if not found.
-        */
-       protected int firstActionWithID(String id, int start) {
-               for (int i = start; i <= this.actionsEnd; i++) {
-                       if (this.actions[i].getID().equals(id)) {
-                               return i;
-                       }
-               }
-               return -1;
-       }
-       
-       /**
-        * Convenience method to move resources
-        */
-       protected void moveResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
-               IProgressMonitor subProgressMonitor = null;
-               if (progressMonitor != null) {
-                       subProgressMonitor = new SubProgressMonitor(progressMonitor, resources.length, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
-               }
-               IWorkspace workspace = resources[0].getWorkspace();
-               try {
-                       workspace.move(resources, destinationPath, false, subProgressMonitor);
-                       this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-               } catch (CoreException e) {
-                       throw new JavaModelException(e);
-               }
-       }
-       /**
-        * Creates and returns a new <code>IJavaElementDelta</code>
-        * on the Java Model.
-        */
-       public JavaElementDelta newJavaElementDelta() {
-               return new JavaElementDelta(getJavaModel());
-       }
-       /*
-        * Removes the last pushed operation from the stack of running operations.
-        * Returns the poped operation or null if the stack was empty.
-        */
-       protected JavaModelOperation popOperation() {
-               ArrayList stack = getCurrentOperationStack();
-               int size = stack.size();
-               if (size > 0) {
-                       if (size == 1) { // top level operation 
-                               operationStacks.setCurrent(null); // release reference (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33927)
-                       }
-                       return (JavaModelOperation)stack.remove(size-1);
-               } else {
-                       return null;
-               }
-       }
-       /*
-        * Registers the given action to be run when the outer most java model operation has finished.
-        * The insertion mode controls whether:
-        * - the action should discard all existing actions with the same id, and be queued at the end (REMOVEALL_APPEND),
-        * - the action should be ignored if there is already an action with the same id (KEEP_EXISTING),
-        * - the action should be queued at the end without looking at existing actions (APPEND)
-        */
-       protected void postAction(IPostAction action, int insertionMode) {
-               if (POST_ACTION_VERBOSE) {
-                       System.out.print("(" + Thread.currentThread() + ") [JavaModelOperation.postAction(IPostAction, int)] Posting action " + action.getID()); //$NON-NLS-1$ //$NON-NLS-2$
-                       switch(insertionMode) {
-                               case REMOVEALL_APPEND:
-                                       System.out.println(" (REMOVEALL_APPEND)"); //$NON-NLS-1$
-                                       break;
-                               case KEEP_EXISTING:
-                                       System.out.println(" (KEEP_EXISTING)"); //$NON-NLS-1$
-                                       break;
-                               case APPEND:
-                                       System.out.println(" (APPEND)"); //$NON-NLS-1$
-                                       break;
-                       }
-               }
-               
-               JavaModelOperation topLevelOp = (JavaModelOperation)getCurrentOperationStack().get(0);
-               IPostAction[] postActions = topLevelOp.actions;
-               if (postActions == null) {
-                       topLevelOp.actions = postActions = new IPostAction[1];
-                       postActions[0] = action;
-                       topLevelOp.actionsEnd = 0;
-               } else {
-                       String id = action.getID();
-                       switch (insertionMode) {
-                               case REMOVEALL_APPEND :
-                                       int index = this.actionsStart-1;
-                                       while ((index = topLevelOp.firstActionWithID(id, index+1)) >= 0) {
-                                               // remove action[index]
-                                               System.arraycopy(postActions, index+1, postActions, index, topLevelOp.actionsEnd - index);
-                                               postActions[topLevelOp.actionsEnd--] = null;
-                                       }
-                                       topLevelOp.addAction(action);
-                                       break;
-                               case KEEP_EXISTING:
-                                       if (topLevelOp.firstActionWithID(id, 0) < 0) {
-                                               topLevelOp.addAction(action);
-                                       }
-                                       break;
-                               case APPEND:
-                                       topLevelOp.addAction(action);
-                                       break;
-                       }
-               }
-       }
-       /*
-        * Returns whether the given path is the prefix of one of the given other paths.
-        */
-       protected boolean prefixesOneOf(IPath path, IPath[] otherPaths) {
-               for (int i = 0, length = otherPaths.length; i < length; i++) {
-                       if (path.isPrefixOf(otherPaths[i])) {
-                               return true;
-                       }
-               }
-               return false;
-       }       
-       /*
-        * Pushes the given operation on the stack of operations currently running in this thread.
-        */
-       protected void pushOperation(JavaModelOperation operation) {
-               getCurrentOperationStack().add(operation);
-       }
-       
-       /**
-        * Main entry point for Java Model operations.  Executes this operation
-        * and registers any deltas created.
-        *
-        * @see IWorkspaceRunnable
-        * @exception CoreException if the operation fails
-        */
-       public void run(IProgressMonitor monitor) throws CoreException {
-               JavaModelManager manager = JavaModelManager.getJavaModelManager();
-               DeltaProcessor deltaProcessor = manager.getDeltaProcessor();
-               int previousDeltaCount = deltaProcessor.javaModelDeltas.size();
-               try {
-                       progressMonitor = monitor;
-                       pushOperation(this);
-                       try {
-                               // computes the root infos before executing the operation
-                               // noop if aready initialized
-                               JavaModelManager.getJavaModelManager().deltaState.initializeRoots();
-                               
-                               executeOperation();
-                       } finally {
-                               if (this.isTopLevelOperation()) {
-                                       this.runPostActions();
-                               }
-                       }
-               } finally {
-
-                       try {
-//                             TODO jsurfer temp-del
-                               // update JavaModel using deltas that were recorded during this operation
-//                             for (int i = previousDeltaCount, size = manager.javaModelDeltas.size(); i < size; i++) {
-//                                     manager.updateJavaModel((IJavaElementDelta)manager.javaModelDeltas.get(i));
-//                             }
-                               
-                               // fire only iff:
-                               // - the operation is a top level operation
-                               // - the operation did produce some delta(s)
-                               // - but the operation has not modified any resource
-                               if (this.isTopLevelOperation()) {
-                                       if ((manager.javaModelDeltas.size() > previousDeltaCount || !manager.reconcileDeltas.isEmpty()) 
-                                                       && !this.hasModifiedResource()) {
-                                               manager.fire(null, JavaModelManager.DEFAULT_CHANGE_EVENT);
-                                       } // else deltas are fired while processing the resource delta
-                               }
-                       } finally {
-                               popOperation();
-                       } 
-               }
-       }
-       /**
-        * Main entry point for Java Model operations. Runs a Java Model Operation as an IWorkspaceRunnable
-        * if not read-only.
-        */
-       public void runOperation(IProgressMonitor monitor) throws JavaModelException {
-               IJavaModelStatus status= verify();
-               if (!status.isOK()) {
-                       throw new JavaModelException(status);
-               }
-               try {
-                       if (isReadOnly()) {
-                               run(monitor);
-                       } else {
-                               // Use IWorkspace.run(...) to ensure that a build will be done in autobuild mode.
-                               // Note that if the tree is locked, this will throw a CoreException, but this is ok
-                               // as this operation is modifying the tree (not read-only) and a CoreException will be thrown anyway.
-                ResourcesPlugin.getWorkspace().run(this, getSchedulingRule(), IWorkspace.AVOID_UPDATE, monitor);
-                       }
-               } catch (CoreException ce) {
-                       if (ce instanceof JavaModelException) {
-                               throw (JavaModelException)ce;
-                       } else {
-                               if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
-                                       Throwable e= ce.getStatus().getException();
-                                       if (e instanceof JavaModelException) {
-                                               throw (JavaModelException) e;
-                                       }
-                               }
-                               throw new JavaModelException(ce);
-                       }
-               }
-       }
-       protected void runPostActions() throws JavaModelException {
-               while (this.actionsStart <= this.actionsEnd) {
-                       IPostAction postAction = this.actions[this.actionsStart++];
-                       if (POST_ACTION_VERBOSE) {
-                               System.out.println("(" + Thread.currentThread() + ") [JavaModelOperation.runPostActions()] Running action " + postAction.getID()); //$NON-NLS-1$ //$NON-NLS-2$
-                       }
-                       postAction.run();
-               }
-       }
-       /*
-        * Registers the given attribute at the given key with the top level operation.
-        */
-       protected void setAttribute(Object key, Object attribute) {
-               JavaModelOperation topLevelOp = (JavaModelOperation)this.getCurrentOperationStack().get(0);
-               if (topLevelOp.attributes == null) {
-                       topLevelOp.attributes = new HashMap();
-               }
-               topLevelOp.attributes.put(key, attribute);
-       }
-       /**
-        * @see IProgressMonitor
-        */
-       public void setCanceled(boolean b) {
-               if (progressMonitor != null) {
-                       progressMonitor.setCanceled(b);
-               }
-       }
-       /**
-        * Sets whether this operation is nested or not.
-        * @see CreateElementInCUOperation#checkCanceled
-        */
-       protected void setNested(boolean nested) {
-               isNested = nested;
-       }
-       /**
-        * @see IProgressMonitor
-        */
-       public void setTaskName(String name) {
-               if (progressMonitor != null) {
-                       progressMonitor.setTaskName(name);
-               }
-       }
-       /**
-        * @see IProgressMonitor
-        */
-       public void subTask(String name) {
-               if (progressMonitor != null) {
-                       progressMonitor.subTask(name);
-               }
-       }
-       /**
-        * Returns a status indicating if there is any known reason
-        * this operation will fail.  Operations are verified before they
-        * are run.
-        *
-        * Subclasses must override if they have any conditions to verify
-        * before this operation executes.
-        *
-        * @see IJavaModelStatus
-        */
-       protected IJavaModelStatus verify() {
-               return commonVerify();
-       }
-       
-       /**
-        * @see IProgressMonitor
-        */
-       public void worked(int work) {
-               if (progressMonitor != null) {
-                       progressMonitor.worked(work);
-                       checkCanceled();
-               }
-       }
-}
+  protected interface IPostAction {
+    /*
+     * Returns the id of this action.
+     * 
+     * @see JavaModelOperation#postAction
+     */
+    String getID();
+
+    /*
+     * Run this action.
+     */
+    void run() throws JavaModelException;
+  }
+
+  /*
+   * Constants controlling the insertion mode of an action.
+   * 
+   * @see JavaModelOperation#postAction
+   */
+  protected static final int APPEND = 1; // insert at the end
+
+  protected static final int REMOVEALL_APPEND = 2; // remove all existing ones with same ID, and add new one at the end
+
+  protected static final int KEEP_EXISTING = 3; // do not insert if already existing with same ID
+
+  /*
+   * Whether tracing post actions is enabled.
+   */
+  protected static boolean POST_ACTION_VERBOSE;
+
+  /*
+   * A list of IPostActions.
+   */
+  protected IPostAction[] actions;
+
+  protected int actionsStart = 0;
+
+  protected int actionsEnd = -1;
+
+  /*
+   * A HashMap of attributes that can be used by operations
+   */
+  protected HashMap attributes;
+
+  public static final String HAS_MODIFIED_RESOURCE_ATTR = "hasModifiedResource"; //$NON-NLS-1$
+
+  public static final String TRUE = "true"; //$NON-NLS-1$
+
+  //public static final String FALSE = "false"; //$NON-NLS-1$
+
+  /**
+   * The elements this operation operates on, or <code>null</code> if this operation does not operate on specific elements.
+   */
+  protected IJavaElement[] fElementsToProcess;
+
+  /**
+   * The parent elements this operation operates with or <code>null</code> if this operation does not operate with specific parent
+   * elements.
+   */
+  protected IJavaElement[] fParentElements;
+
+  /**
+   * An empty collection of <code>IJavaElement</code> s - the common empty result if no elements are created, or if this operation
+   * is not actually executed.
+   */
+  protected static IJavaElement[] NO_ELEMENTS = new IJavaElement[] {};
+
+  /**
+   * The elements created by this operation - empty until the operation actually creates elements.
+   */
+  protected IJavaElement[] resultElements = NO_ELEMENTS;
+
+  /**
+   * The progress monitor passed into this operation
+   */
+  protected IProgressMonitor progressMonitor = null;
+
+  /**
+   * A flag indicating whether this operation is nested.
+   */
+  protected boolean isNested = false;
+
+  /**
+   * Conflict resolution policy - by default do not force (fail on a conflict).
+   */
+  protected boolean force = false;
+
+  /*
+   * A per thread stack of java model operations (PerThreadObject of ArrayList).
+   */
+  protected static PerThreadObject operationStacks = new PerThreadObject();
+
+  protected JavaModelOperation() {
+  }
+
+  /**
+   * A common constructor for all Java Model operations.
+   */
+  protected JavaModelOperation(IJavaElement[] elements) {
+    fElementsToProcess = elements;
+  }
+
+  /**
+   * Common constructor for all Java Model operations.
+   */
+  protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements) {
+    fElementsToProcess = elementsToProcess;
+    fParentElements = parentElements;
+  }
+
+  /**
+   * A common constructor for all Java Model operations.
+   */
+  protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) {
+    fElementsToProcess = elementsToProcess;
+    fParentElements = parentElements;
+    this.force = force;
+  }
+
+  /**
+   * A common constructor for all Java Model operations.
+   */
+  protected JavaModelOperation(IJavaElement[] elements, boolean force) {
+    fElementsToProcess = elements;
+    this.force = force;
+  }
+
+  /**
+   * Common constructor for all Java Model operations.
+   */
+  protected JavaModelOperation(IJavaElement element) {
+    fElementsToProcess = new IJavaElement[] { element };
+  }
+
+  /**
+   * A common constructor for all Java Model operations.
+   */
+  protected JavaModelOperation(IJavaElement element, boolean force) {
+    fElementsToProcess = new IJavaElement[] { element };
+    this.force = force;
+  }
+
+  /*
+   * Registers the given action at the end of the list of actions to run.
+   */
+  protected void addAction(IPostAction action) {
+    int length = this.actions.length;
+    if (length == ++this.actionsEnd) {
+      System.arraycopy(this.actions, 0, this.actions = new IPostAction[length * 2], 0, length);
+    }
+    this.actions[this.actionsEnd] = action;
+  }
+
+  /*
+   * Registers the given delta with the Java Model Manager.
+   */
+  protected void addDelta(IJavaElementDelta delta) {
+    JavaModelManager.getJavaModelManager().registerJavaModelDelta(delta);
+  }
+
+  /*
+   * Registers the given reconcile delta with the Java Model Manager.
+   */
+  protected void addReconcileDelta(IWorkingCopy workingCopy, IJavaElementDelta delta) {
+    HashMap reconcileDeltas = JavaModelManager.getJavaModelManager().reconcileDeltas;
+    JavaElementDelta previousDelta = (JavaElementDelta) reconcileDeltas.get(workingCopy);
+    if (previousDelta != null) {
+      IJavaElementDelta[] children = delta.getAffectedChildren();
+      for (int i = 0, length = children.length; i < length; i++) {
+        JavaElementDelta child = (JavaElementDelta) children[i];
+        previousDelta.insertDeltaTree(child.getElement(), child);
+      }
+    } else {
+      reconcileDeltas.put(workingCopy, delta);
+    }
+  }
+
+  /*
+   * Deregister the reconcile delta for the given working copy
+   */
+  protected void removeReconcileDelta(IWorkingCopy workingCopy) {
+    JavaModelManager.getJavaModelManager().reconcileDeltas.remove(workingCopy);
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public void beginTask(String name, int totalWork) {
+    if (progressMonitor != null) {
+      progressMonitor.beginTask(name, totalWork);
+    }
+  }
+
+  /**
+   * Checks with the progress monitor to see whether this operation should be canceled. An operation should regularly call this
+   * method during its operation so that the user can cancel it.
+   * 
+   * @exception OperationCanceledException
+   *              if cancelling the operation has been requested
+   * @see IProgressMonitor#isCanceled
+   */
+  protected void checkCanceled() {
+    if (isCanceled()) {
+      throw new OperationCanceledException(Util.bind("operation.cancelled")); //$NON-NLS-1$
+    }
+  }
+
+  /**
+   * Common code used to verify the elements this operation is processing.
+   * 
+   * @see JavaModelOperation#verify()
+   */
+  protected IJavaModelStatus commonVerify() {
+    if (fElementsToProcess == null || fElementsToProcess.length == 0) {
+      return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
+    }
+    for (int i = 0; i < fElementsToProcess.length; i++) {
+      if (fElementsToProcess[i] == null) {
+        return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
+      }
+    }
+    return JavaModelStatus.VERIFIED_OK;
+  }
+
+  /**
+   * Convenience method to copy resources
+   */
+  protected void copyResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
+    IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
+    IWorkspace workspace = resources[0].getWorkspace();
+    try {
+      workspace.copy(resources, destinationPath, false, subProgressMonitor);
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * Convenience method to create a file
+   */
+  protected void createFile(IContainer folder, String name, InputStream contents, boolean force) throws JavaModelException {
+    IFile file = folder.getFile(new Path(name));
+    try {
+      file.create(contents, force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, getSubProgressMonitor(1));
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * Convenience method to create a folder
+   */
+  protected void createFolder(IContainer parentFolder, String name, boolean force) throws JavaModelException {
+    IFolder folder = parentFolder.getFolder(new Path(name));
+    try {
+      // we should use true to create the file locally. Only VCM should use tru/false
+      folder.create(force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, true, // local
+          getSubProgressMonitor(1));
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * Convenience method to delete an empty package fragment
+   */
+  protected void deleteEmptyPackageFragment(IPackageFragment fragment, boolean force, IResource rootResource)
+      throws JavaModelException {
+
+    IContainer resource = (IContainer) fragment.getResource();
+
+    try {
+      resource.delete(force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, getSubProgressMonitor(1));
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+      while (resource instanceof IFolder) {
+        // deleting a package: delete the parent if it is empty (eg. deleting x.y where folder x doesn't have resources but y)
+        // without deleting the package fragment root
+        resource = resource.getParent();
+        if (!resource.equals(rootResource) && resource.members().length == 0) {
+          resource.delete(force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, getSubProgressMonitor(1));
+          this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+        }
+      }
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * Convenience method to delete a resource
+   */
+  protected void deleteResource(IResource resource, int flags) throws JavaModelException {
+    try {
+      resource.delete(flags, getSubProgressMonitor(1));
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * Convenience method to delete resources
+   */
+  protected void deleteResources(IResource[] resources, boolean force) throws JavaModelException {
+    if (resources == null || resources.length == 0)
+      return;
+    IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
+    IWorkspace workspace = resources[0].getWorkspace();
+    try {
+      workspace.delete(resources, force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, subProgressMonitor);
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public void done() {
+    if (progressMonitor != null) {
+      progressMonitor.done();
+    }
+  }
+
+  /*
+   * Returns whether the given path is equals to one of the given other paths.
+   */
+  protected boolean equalsOneOf(IPath path, IPath[] otherPaths) {
+    for (int i = 0, length = otherPaths.length; i < length; i++) {
+      if (path.equals(otherPaths[i])) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Verifies the operation can proceed and executes the operation. Subclasses should override <code>#verify</code> and
+   * <code>executeOperation</code> to implement the specific operation behavior.
+   * 
+   * @exception JavaModelException
+   *              The operation has failed.
+   */
+  //   protected void execute() throws JavaModelException {
+  //           IJavaModelStatus status= verify();
+  //           if (status.isOK()) {
+  //                   // if first time here, computes the root infos before executing the operation
+  //                   DeltaProcessor deltaProcessor = JavaModelManager.getJavaModelManager().deltaProcessor;
+  //                   if (deltaProcessor.roots == null) {
+  //                     deltaProcessor.initializeRoots();
+  //                   }
+  //                   executeOperation();
+  //           } else {
+  //                   throw new JavaModelException(status);
+  //           }
+  //   }
+  /**
+   * Convenience method to run an operation within this operation
+   */
+  public void executeNestedOperation(JavaModelOperation operation, int subWorkAmount) throws JavaModelException {
+    IProgressMonitor subProgressMonitor = getSubProgressMonitor(subWorkAmount);
+    // fix for 1FW7IKC, part (1)
+    try {
+      operation.setNested(true);
+      operation.run(subProgressMonitor);
+    } catch (CoreException ce) {
+      if (ce instanceof JavaModelException) {
+        throw (JavaModelException) ce;
+      } else {
+        // translate the core exception to a java model exception
+        if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
+          Throwable e = ce.getStatus().getException();
+          if (e instanceof JavaModelException) {
+            throw (JavaModelException) e;
+          }
+        }
+        throw new JavaModelException(ce);
+      }
+    }
+  }
+
+  /**
+   * Performs the operation specific behavior. Subclasses must override.
+   */
+  protected abstract void executeOperation() throws JavaModelException;
+
+  /*
+   * Returns the attribute registered at the given key with the top level operation. Returns null if no such attribute is found.
+   */
+  protected Object getAttribute(Object key) {
+    ArrayList stack = this.getCurrentOperationStack();
+    if (stack.size() == 0)
+      return null;
+    JavaModelOperation topLevelOp = (JavaModelOperation) stack.get(0);
+    if (topLevelOp.attributes == null) {
+      return null;
+    } else {
+      return topLevelOp.attributes.get(key);
+    }
+  }
+
+  /**
+   * Returns the compilation unit the given element is contained in, or the element itself (if it is a compilation unit), otherwise
+   * <code>null</code>.
+   */
+  protected ICompilationUnit getCompilationUnitFor(IJavaElement element) {
+
+    return ((JavaElement) element).getCompilationUnit();
+  }
+
+  /*
+   * Returns the stack of operations running in the current thread. Returns an empty stack if no operations are currently running in
+   * this thread.
+   */
+  protected ArrayList getCurrentOperationStack() {
+    ArrayList stack = (ArrayList) operationStacks.getCurrent();
+    if (stack == null) {
+      stack = new ArrayList();
+      operationStacks.setCurrent(stack);
+    }
+    return stack;
+  }
+
+  /**
+   * Returns the elements to which this operation applies, or <code>null</code> if not applicable.
+   */
+  protected IJavaElement[] getElementsToProcess() {
+    return fElementsToProcess;
+  }
+
+  /**
+   * Returns the element to which this operation applies, or <code>null</code> if not applicable.
+   */
+  protected IJavaElement getElementToProcess() {
+    if (fElementsToProcess == null || fElementsToProcess.length == 0) {
+      return null;
+    }
+    return fElementsToProcess[0];
+  }
+
+  /**
+   * Returns the Java Model this operation is operating in.
+   */
+  public IJavaModel getJavaModel() {
+    if (fElementsToProcess == null || fElementsToProcess.length == 0) {
+      return getParentElement().getJavaModel();
+    } else {
+      return fElementsToProcess[0].getJavaModel();
+    }
+  }
+
+  //   protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException {
+  //           IPath rootPath = root.getPath();
+  //           IClasspathEntry[] classpath = root.getJavaProject().getRawClasspath();
+  //           int length = classpath.length;
+  //           IPath[] result = new IPath[length];
+  //           int index = 0;
+  //           for (int i = 0; i < length; i++) {
+  //                   IPath path = classpath[i].getPath();
+  //                   if (rootPath.isPrefixOf(path) && !rootPath.equals(path)) {
+  //                           result[index++] = path;
+  //                   }
+  //           }
+  //           if (index < length) {
+  //                   System.arraycopy(result, 0, result = new IPath[index], 0, index);
+  //           }
+  //           return result;
+  //   }
+  /**
+   * Returns the parent element to which this operation applies, or <code>null</code> if not applicable.
+   */
+  protected IJavaElement getParentElement() {
+    if (fParentElements == null || fParentElements.length == 0) {
+      return null;
+    }
+    return fParentElements[0];
+  }
+
+  /**
+   * Returns the parent elements to which this operation applies, or <code>null</code> if not applicable.
+   */
+  protected IJavaElement[] getParentElements() {
+    return fParentElements;
+  }
+
+  /**
+   * Returns the elements created by this operation.
+   */
+  public IJavaElement[] getResultElements() {
+    return resultElements;
+  }
+
+  /*
+   * Returns the scheduling rule for this operation (i.e. the resource that needs to be locked while this operation is running.
+   * Subclasses can override.
+   */
+  protected ISchedulingRule getSchedulingRule() {
+    return ResourcesPlugin.getWorkspace().getRoot();
+  }
+
+  /**
+   * Creates and returns a subprogress monitor if appropriate.
+   */
+  protected IProgressMonitor getSubProgressMonitor(int workAmount) {
+    IProgressMonitor sub = null;
+    if (progressMonitor != null) {
+      sub = new SubProgressMonitor(progressMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+    }
+    return sub;
+  }
+
+  /**
+   * Returns whether this operation has performed any resource modifications. Returns false if this operation has not been executed
+   * yet.
+   */
+  public boolean hasModifiedResource() {
+    return !this.isReadOnly() && this.getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE;
+  }
+
+  public void internalWorked(double work) {
+    if (progressMonitor != null) {
+      progressMonitor.internalWorked(work);
+    }
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public boolean isCanceled() {
+    if (progressMonitor != null) {
+      return progressMonitor.isCanceled();
+    }
+    return false;
+  }
+
+  /**
+   * Returns <code>true</code> if this operation performs no resource modifications, otherwise <code>false</code>. Subclasses
+   * must override.
+   */
+  public boolean isReadOnly() {
+    return false;
+  }
+
+  /*
+   * Returns whether this operation is the first operation to run in the current thread.
+   */
+  protected boolean isTopLevelOperation() {
+    ArrayList stack;
+    return (stack = this.getCurrentOperationStack()).size() > 0 && stack.get(0) == this;
+  }
+
+  /*
+   * Returns the index of the first registered action with the given id, starting from a given position. Returns -1 if not found.
+   */
+  protected int firstActionWithID(String id, int start) {
+    for (int i = start; i <= this.actionsEnd; i++) {
+      if (this.actions[i].getID().equals(id)) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Convenience method to move resources
+   */
+  protected void moveResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
+    IProgressMonitor subProgressMonitor = null;
+    if (progressMonitor != null) {
+      subProgressMonitor = new SubProgressMonitor(progressMonitor, resources.length,
+          SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+    }
+    IWorkspace workspace = resources[0].getWorkspace();
+    try {
+      workspace.move(resources, destinationPath, false, subProgressMonitor);
+      this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
+    } catch (CoreException e) {
+      throw new JavaModelException(e);
+    }
+  }
+
+  /**
+   * Creates and returns a new <code>IJavaElementDelta</code> on the Java Model.
+   */
+  public JavaElementDelta newJavaElementDelta() {
+    return new JavaElementDelta(getJavaModel());
+  }
+
+  /*
+   * Removes the last pushed operation from the stack of running operations. Returns the poped operation or null if the stack was
+   * empty.
+   */
+  protected JavaModelOperation popOperation() {
+    ArrayList stack = getCurrentOperationStack();
+    int size = stack.size();
+    if (size > 0) {
+      if (size == 1) { // top level operation
+        operationStacks.setCurrent(null); // release reference (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33927)
+      }
+      return (JavaModelOperation) stack.remove(size - 1);
+    } else {
+      return null;
+    }
+  }
+
+  /*
+   * Registers the given action to be run when the outer most java model operation has finished. The insertion mode controls
+   * whether: - the action should discard all existing actions with the same id, and be queued at the end (REMOVEALL_APPEND), - the
+   * action should be ignored if there is already an action with the same id (KEEP_EXISTING), - the action should be queued at the
+   * end without looking at existing actions (APPEND)
+   */
+  protected void postAction(IPostAction action, int insertionMode) {
+    if (POST_ACTION_VERBOSE) {
+      System.out
+          .print("(" + Thread.currentThread() + ") [JavaModelOperation.postAction(IPostAction, int)] Posting action " + action.getID()); //$NON-NLS-1$ //$NON-NLS-2$
+      switch (insertionMode) {
+      case REMOVEALL_APPEND:
+        System.out.println(" (REMOVEALL_APPEND)"); //$NON-NLS-1$
+        break;
+      case KEEP_EXISTING:
+        System.out.println(" (KEEP_EXISTING)"); //$NON-NLS-1$
+        break;
+      case APPEND:
+        System.out.println(" (APPEND)"); //$NON-NLS-1$
+        break;
+      }
+    }
+
+    JavaModelOperation topLevelOp = (JavaModelOperation) getCurrentOperationStack().get(0);
+    IPostAction[] postActions = topLevelOp.actions;
+    if (postActions == null) {
+      topLevelOp.actions = postActions = new IPostAction[1];
+      postActions[0] = action;
+      topLevelOp.actionsEnd = 0;
+    } else {
+      String id = action.getID();
+      switch (insertionMode) {
+      case REMOVEALL_APPEND:
+        int index = this.actionsStart - 1;
+        while ((index = topLevelOp.firstActionWithID(id, index + 1)) >= 0) {
+          // remove action[index]
+          System.arraycopy(postActions, index + 1, postActions, index, topLevelOp.actionsEnd - index);
+          postActions[topLevelOp.actionsEnd--] = null;
+        }
+        topLevelOp.addAction(action);
+        break;
+      case KEEP_EXISTING:
+        if (topLevelOp.firstActionWithID(id, 0) < 0) {
+          topLevelOp.addAction(action);
+        }
+        break;
+      case APPEND:
+        topLevelOp.addAction(action);
+        break;
+      }
+    }
+  }
+
+  /*
+   * Returns whether the given path is the prefix of one of the given other paths.
+   */
+  protected boolean prefixesOneOf(IPath path, IPath[] otherPaths) {
+    for (int i = 0, length = otherPaths.length; i < length; i++) {
+      if (path.isPrefixOf(otherPaths[i])) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /*
+   * Pushes the given operation on the stack of operations currently running in this thread.
+   */
+  protected void pushOperation(JavaModelOperation operation) {
+    getCurrentOperationStack().add(operation);
+  }
+
+  /**
+   * Main entry point for Java Model operations. Executes this operation and registers any deltas created.
+   * 
+   * @see IWorkspaceRunnable
+   * @exception CoreException
+   *              if the operation fails
+   */
+  public void run(IProgressMonitor monitor) throws CoreException {
+    JavaModelManager manager = JavaModelManager.getJavaModelManager();
+    DeltaProcessor deltaProcessor = manager.getDeltaProcessor();
+    int previousDeltaCount = deltaProcessor.javaModelDeltas.size();
+    try {
+      progressMonitor = monitor;
+      pushOperation(this);
+      try {
+        // computes the root infos before executing the operation
+        // noop if aready initialized
+        JavaModelManager.getJavaModelManager().deltaState.initializeRoots();
+
+        executeOperation();
+      } finally {
+        if (this.isTopLevelOperation()) {
+          this.runPostActions();
+        }
+      }
+    } finally {
+
+      try {
+        // TODO jsurfer temp-del
+        // update JavaModel using deltas that were recorded during this operation
+        // for (int i = previousDeltaCount, size = manager.javaModelDeltas.size(); i < size; i++) {
+        // manager.updateJavaModel((IJavaElementDelta)manager.javaModelDeltas.get(i));
+        // }
+
+        // fire only iff:
+        // - the operation is a top level operation
+        // - the operation did produce some delta(s)
+        // - but the operation has not modified any resource
+        if (this.isTopLevelOperation()) {
+          if ((manager.javaModelDeltas.size() > previousDeltaCount || !manager.reconcileDeltas.isEmpty())
+              && !this.hasModifiedResource()) {
+            manager.fire(null, JavaModelManager.DEFAULT_CHANGE_EVENT);
+          } // else deltas are fired while processing the resource delta
+        }
+      } finally {
+        popOperation();
+      }
+    }
+  }
+
+  /**
+   * Main entry point for Java Model operations. Runs a Java Model Operation as an IWorkspaceRunnable if not read-only.
+   */
+  public void runOperation(IProgressMonitor monitor) throws JavaModelException {
+    IJavaModelStatus status = verify();
+    if (!status.isOK()) {
+      throw new JavaModelException(status);
+    }
+    try {
+      if (isReadOnly()) {
+        run(monitor);
+      } else {
+        // Use IWorkspace.run(...) to ensure that a build will be done in autobuild mode.
+        // Note that if the tree is locked, this will throw a CoreException, but this is ok
+        // as this operation is modifying the tree (not read-only) and a CoreException will be thrown anyway.
+        ResourcesPlugin.getWorkspace().run(this, getSchedulingRule(), IWorkspace.AVOID_UPDATE, monitor);
+      }
+    } catch (CoreException ce) {
+      if (ce instanceof JavaModelException) {
+        throw (JavaModelException) ce;
+      } else {
+        if (ce.getStatus().getCode() == IResourceStatus.OPERATION_FAILED) {
+          Throwable e = ce.getStatus().getException();
+          if (e instanceof JavaModelException) {
+            throw (JavaModelException) e;
+          }
+        }
+        throw new JavaModelException(ce);
+      }
+    }
+  }
+
+  protected void runPostActions() throws JavaModelException {
+    while (this.actionsStart <= this.actionsEnd) {
+      IPostAction postAction = this.actions[this.actionsStart++];
+      if (POST_ACTION_VERBOSE) {
+        System.out
+            .println("(" + Thread.currentThread() + ") [JavaModelOperation.runPostActions()] Running action " + postAction.getID()); //$NON-NLS-1$ //$NON-NLS-2$
+      }
+      postAction.run();
+    }
+  }
+
+  /*
+   * Registers the given attribute at the given key with the top level operation.
+   */
+  protected void setAttribute(Object key, Object attribute) {
+    JavaModelOperation topLevelOp = (JavaModelOperation) this.getCurrentOperationStack().get(0);
+    if (topLevelOp.attributes == null) {
+      topLevelOp.attributes = new HashMap();
+    }
+    topLevelOp.attributes.put(key, attribute);
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public void setCanceled(boolean b) {
+    if (progressMonitor != null) {
+      progressMonitor.setCanceled(b);
+    }
+  }
+
+  /**
+   * Sets whether this operation is nested or not.
+   * 
+   * @see CreateElementInCUOperation#checkCanceled
+   */
+  protected void setNested(boolean nested) {
+    isNested = nested;
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public void setTaskName(String name) {
+    if (progressMonitor != null) {
+      progressMonitor.setTaskName(name);
+    }
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public void subTask(String name) {
+    if (progressMonitor != null) {
+      progressMonitor.subTask(name);
+    }
+  }
+
+  /**
+   * Returns a status indicating if there is any known reason this operation will fail. Operations are verified before they are run.
+   * 
+   * Subclasses must override if they have any conditions to verify before this operation executes.
+   * 
+   * @see IJavaModelStatus
+   */
+  protected IJavaModelStatus verify() {
+    return commonVerify();
+  }
+
+  /**
+   * @see IProgressMonitor
+   */
+  public void worked(int work) {
+    if (progressMonitor != null) {
+      progressMonitor.worked(work);
+      checkCanceled();
+    }
+  }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTableViewer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTableViewer.java
new file mode 100644 (file)
index 0000000..54778c5
--- /dev/null
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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 net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.ui.IWorkingCopyProvider;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.Widget;
+
+/**
+ * Extends a  TableViewer to allow more performance when showing error ticks.
+ * A <code>ProblemItemMapper</code> is contained that maps all items in
+ * the tree to underlying resource
+ */
+public class ProblemTableViewer extends TableViewer {
+
+       protected ResourceToItemsMapper fResourceToItemsMapper;
+
+       /**
+        * Constructor for ProblemTableViewer.
+        * @param parent
+        */
+       public ProblemTableViewer(Composite parent) {
+               super(parent);
+               initMapper();
+       }
+
+       /**
+        * Constructor for ProblemTableViewer.
+        * @param parent
+        * @param style
+        */
+       public ProblemTableViewer(Composite parent, int style) {
+               super(parent, style);
+               initMapper();
+       }
+
+       /**
+        * Constructor for ProblemTableViewer.
+        * @param table
+        */
+       public ProblemTableViewer(Table table) {
+               super(table);
+               initMapper();
+       }
+
+       private void initMapper() {
+               fResourceToItemsMapper= new ResourceToItemsMapper(this);
+       }
+       
+       /*
+        * @see StructuredViewer#mapElement(Object, Widget)
+        */
+       protected void mapElement(Object element, Widget item) {
+               super.mapElement(element, item);
+               if (item instanceof Item) {
+                       fResourceToItemsMapper.addToMap(element, (Item) item);
+               }
+       }
+
+       /*
+        * @see StructuredViewer#unmapElement(Object, Widget)
+        */
+       protected void unmapElement(Object element, Widget item) {
+               if (item instanceof Item) {
+                       fResourceToItemsMapper.removeFromMap(element, (Item) item);
+               }               
+               super.unmapElement(element, item);
+       }
+
+       /*
+        * @see StructuredViewer#unmapAllElements()
+        */
+       protected void unmapAllElements() {
+               fResourceToItemsMapper.clearMap();
+               super.unmapAllElements();
+       }
+       
+       /*
+        * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent)
+        */
+       protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
+               if (event instanceof ProblemsLabelChangedEvent) {
+                       ProblemsLabelChangedEvent e= (ProblemsLabelChangedEvent) event;
+                       if (!e.isMarkerChange() && canIgnoreChangesFromAnnotionModel()) {
+                               return;
+                       }
+               }
+               
+               Object[] changed= event.getElements();
+               if (changed != null && !fResourceToItemsMapper.isEmpty()) {
+                       ArrayList others= new ArrayList(changed.length);
+                       for (int i= 0; i < changed.length; i++) {
+                               Object curr= changed[i];
+                               if (curr instanceof IResource) {
+                                       fResourceToItemsMapper.resourceChanged((IResource) curr);
+                               } else {
+                                       others.add(curr);
+                               }
+                       }
+                       if (others.isEmpty()) {
+                               return;
+                       }
+                       event= new LabelProviderChangedEvent((IBaseLabelProvider) event.getSource(), others.toArray());
+               }
+               super.handleLabelProviderChanged(event);
+       }
+       
+       /**
+        * Answers whether this viewer can ignore label provider changes resulting from
+        * marker changes in annotation models
+        */
+       private boolean canIgnoreChangesFromAnnotionModel() {
+               Object contentProvider= getContentProvider();
+               return contentProvider instanceof IWorkingCopyProvider && !((IWorkingCopyProvider)contentProvider).providesWorkingCopies();
+       }
+}
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTreeViewer.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ProblemTreeViewer.java
new file mode 100644 (file)
index 0000000..6261f4d
--- /dev/null
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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 net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+
+import org.eclipse.core.resources.IResource;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Item;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+
+import net.sourceforge.phpdt.core.IMember;
+
+import net.sourceforge.phpdt.ui.IWorkingCopyProvider;
+import net.sourceforge.phpdt.ui.ProblemsLabelDecorator.ProblemsLabelChangedEvent;
+
+/**
+ * Extends a  TreeViewer to allow more performance when showing error ticks.
+ * A <code>ProblemItemMapper</code> is contained that maps all items in
+ * the tree to underlying resource
+ */
+public class ProblemTreeViewer extends TreeViewer {
+
+       protected ResourceToItemsMapper fResourceToItemsMapper;
+
+       /*
+        * @see TreeViewer#TreeViewer(Composite)
+        */
+       public ProblemTreeViewer(Composite parent) {
+               super(parent);
+               initMapper();
+       }
+
+       /*
+        * @see TreeViewer#TreeViewer(Composite, int)
+        */
+       public ProblemTreeViewer(Composite parent, int style) {
+               super(parent, style);
+               initMapper();
+       }
+
+       /*
+        * @see TreeViewer#TreeViewer(Tree)
+        */
+       public ProblemTreeViewer(Tree tree) {
+               super(tree);
+               initMapper();
+       }
+       
+       private void initMapper() {
+               fResourceToItemsMapper= new ResourceToItemsMapper(this);
+       }
+       
+       
+       /*
+        * @see StructuredViewer#mapElement(Object, Widget)
+        */
+       protected void mapElement(Object element, Widget item) {
+               super.mapElement(element, item);
+               if (item instanceof Item) {
+                       fResourceToItemsMapper.addToMap(element, (Item) item);
+               }
+       }
+
+       /*
+        * @see StructuredViewer#unmapElement(Object, Widget)
+        */
+       protected void unmapElement(Object element, Widget item) {
+               if (item instanceof Item) {
+                       fResourceToItemsMapper.removeFromMap(element, (Item) item);
+               }               
+               super.unmapElement(element, item);
+       }
+
+       /*
+        * @see StructuredViewer#unmapAllElements()
+        */
+       protected void unmapAllElements() {
+               fResourceToItemsMapper.clearMap();
+               super.unmapAllElements();
+       }
+
+       /*
+        * @see ContentViewer#handleLabelProviderChanged(LabelProviderChangedEvent)
+        */
+       protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
+               if (event instanceof ProblemsLabelChangedEvent) {
+                       ProblemsLabelChangedEvent e= (ProblemsLabelChangedEvent) event;
+                       if (!e.isMarkerChange() && canIgnoreChangesFromAnnotionModel()) {
+                               return;
+                       }
+               }               
+               
+               Object[] changed= event.getElements();
+               if (changed != null && !fResourceToItemsMapper.isEmpty()) {
+                       ArrayList others= new ArrayList();
+                       for (int i= 0; i < changed.length; i++) {
+                               Object curr= changed[i];
+                               if (curr instanceof IResource) {
+                                       fResourceToItemsMapper.resourceChanged((IResource) curr);
+                               } else {
+                                       others.add(curr);
+                               }
+                       }
+                       if (others.isEmpty()) {
+                               return;
+                       }
+                       event= new LabelProviderChangedEvent((IBaseLabelProvider) event.getSource(), others.toArray());
+               }
+               super.handleLabelProviderChanged(event);
+       }
+       
+       /**
+        * Answers whether this viewer can ignore label provider changes resulting from
+        * marker changes in annotation models
+        */
+       private boolean canIgnoreChangesFromAnnotionModel() {
+               Object contentProvider= getContentProvider();
+               return contentProvider instanceof IWorkingCopyProvider && !((IWorkingCopyProvider)contentProvider).providesWorkingCopies();
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jface.viewers.AbstractTreeViewer#isExpandable(java.lang.Object)
+        */
+       public boolean isExpandable(Object element) {
+               // workaround for 65762
+               if (hasFilters() && element instanceof IMember) {
+                       return getFilteredChildren(element).length > 0;
+               }
+               return super.isExpandable(element);
+       }
+}
+
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ResourceToItemsMapper.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/ui/viewsupport/ResourceToItemsMapper.java
new file mode 100644 (file)
index 0000000..ee58b89
--- /dev/null
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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 net.sourceforge.phpdt.internal.ui.viewsupport;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Stack;
+
+import org.eclipse.core.resources.IResource;
+
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Item;
+
+import org.eclipse.jface.viewers.ContentViewer;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.IViewerLabelProvider;
+import org.eclipse.jface.viewers.ViewerLabel;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IJavaElement;
+
+/**
+ * Helper class for updating error markers and other decorators that work on resources.
+ * Items are mapped to their element's underlying resource.
+ * Method <code>resourceChanged</code> updates all items that are affected from the changed
+ * elements.
+ */
+public class ResourceToItemsMapper {
+
+       private static final int NUMBER_LIST_REUSE= 10;
+
+       // map from resource to item
+       private HashMap fResourceToItem;
+       private Stack fReuseLists;
+       
+       private ContentViewer fContentViewer;
+
+       public ResourceToItemsMapper(ContentViewer viewer) {
+               fResourceToItem= new HashMap();
+               fReuseLists= new Stack();
+               
+               fContentViewer= viewer;
+       }
+
+       /**
+        * Must be called from the UI thread.
+        */
+       public void resourceChanged(IResource changedResource) {
+               Object obj= fResourceToItem.get(changedResource);
+               if (obj == null) {
+                       // not mapped
+               } else if (obj instanceof Item) {
+                       updateItem((Item) obj);
+               } else { // List of Items
+                       List list= (List) obj;
+                       for (int k= 0; k < list.size(); k++) {
+                               updateItem((Item) list.get(k));
+                       }
+               }
+       }
+               
+       private void updateItem(Item item) {
+               if (!item.isDisposed()) { // defensive code
+                       ILabelProvider lprovider= (ILabelProvider) fContentViewer.getLabelProvider();
+                       
+                       Object data= item.getData();
+                       
+                       // If it is an IItemLabelProvider than short circuit: patch Tod (bug 55012)
+                       if (lprovider instanceof IViewerLabelProvider) {
+                               IViewerLabelProvider provider= (IViewerLabelProvider) lprovider;
+                               
+                               ViewerLabel updateLabel= new ViewerLabel(item.getText(), item.getImage());
+                               provider.updateLabel(updateLabel, data);
+                               
+                               if (updateLabel.hasNewImage()) {
+                                       item.setImage(updateLabel.getImage());
+                               }
+                               if (updateLabel.hasNewText()) {
+                                       item.setText(updateLabel.getText());
+                               }
+                       } else {
+                               Image oldImage= item.getImage();
+                               Image image= lprovider.getImage(data);
+                               if (image != null && !image.equals(oldImage)) {
+                                       item.setImage(image);
+                               }
+                               String oldText= item.getText();
+                               String text= lprovider.getText(data);
+                               if (text != null && !text.equals(oldText)) {
+                                       item.setText(text);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Adds a new item to the map.
+        * @param element Element to map
+        * @param item The item used for the element
+        */
+       public void addToMap(Object element, Item item) {
+               IResource resource= getCorrespondingResource(element);
+               if (resource != null) {
+                       Object existingMapping= fResourceToItem.get(resource);
+                       if (existingMapping == null) {
+                               fResourceToItem.put(resource, item);
+                       } else if (existingMapping instanceof Item) {
+                               if (existingMapping != item) {
+                                       List list= getNewList();
+                                       list.add(existingMapping);
+                                       list.add(item);
+                                       fResourceToItem.put(resource, list);
+                               }
+                       } else { // List                        
+                               List list= (List) existingMapping;
+                               if (!list.contains(item)) {
+                                       list.add(item);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Removes an element from the map.
+        */     
+       public void removeFromMap(Object element, Item item) {
+               IResource resource= getCorrespondingResource(element);
+               if (resource != null) {
+                       Object existingMapping= fResourceToItem.get(resource);
+                       if (existingMapping == null) {
+                               return;
+                       } else if (existingMapping instanceof Item) {
+                               fResourceToItem.remove(resource);
+                       } else { // List
+                               List list= (List) existingMapping;
+                               list.remove(item);
+                               if (list.isEmpty()) {
+                                       fResourceToItem.remove(list);
+                                       releaseList(list);
+                               }
+                       }
+               }
+       }
+       
+       private List getNewList() {
+               if (!fReuseLists.isEmpty()) {
+                       return (List) fReuseLists.pop();
+               }
+               return new ArrayList(2);
+       }
+       
+       private void releaseList(List list) {
+               if (fReuseLists.size() < NUMBER_LIST_REUSE) {
+                       fReuseLists.push(list);
+               }
+       }
+       
+       /**
+        * Clears the map.
+        */
+       public void clearMap() {
+               fResourceToItem.clear();
+       }
+       
+       /**
+        * Tests if the map is empty
+        */
+       public boolean isEmpty() {
+               return fResourceToItem.isEmpty();
+       }       
+       
+       /**
+        * Method that decides which elements can have error markers
+        * Returns null if an element can not have error markers.
+        */     
+       private static IResource getCorrespondingResource(Object element) {
+               if (element instanceof IJavaElement) {
+                       IJavaElement elem= (IJavaElement) element;
+                       if (!elem.isReadOnly()) { // only modifieable elements can get error ticks
+                               IResource res= elem.getResource();
+                               if (res == null) {
+                                       ICompilationUnit cu= (ICompilationUnit) elem.getAncestor(IJavaElement.COMPILATION_UNIT);
+                                       if (cu != null) {
+                                               // elements in compilation units are mapped to the underlying resource of the original cu
+                                               res= cu.getResource();
+                                       }
+                               }
+                               return res; 
+                       }
+                       return null;
+               } else if (element instanceof IResource) {
+                       return (IResource) element;
+               }
+               return null;
+       }
+       
+}
index 03de9a1..6bb3fd6 100644 (file)
@@ -21,38 +21,38 @@ import org.eclipse.ui.IWorkbenchActionConstants;
 public interface IContextMenuConstants {
        
        
-//     /**
-//      * Type hierarchy view part: pop-up menu target ID for type hierarchy viewer
-//      * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.typehierarchy"</code>).
-//      * 
-//      * @since 2.0
-//      */
-//     public static final String TARGET_ID_HIERARCHY_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".typehierarchy"; //$NON-NLS-1$ 
-//
-//     /**
-//      * Type hierarchy view part: pop-up menu target ID for supertype hierarchy viewer
-//      * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.supertypes"</code>).
-//      * 
-//      * @since 2.0
-//      */
-//     public static final String TARGET_ID_SUPERTYPES_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".supertypes"; //$NON-NLS-1$   
-//
-//     /**
-//      * Type hierarchy view part: Pop-up menu target ID for the subtype hierarchy viewer
-//      * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.subtypes"</code>).
-//      * 
-//      * @since 2.0
-//      */
-//     public static final String TARGET_ID_SUBTYPES_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".subtypes"; //$NON-NLS-1$       
-//
-//     /**
-//      * Type hierarchy view part: pop-up menu target ID for the meber viewer
-//      * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.members"</code>).
-//      * 
-//      * @since 2.0
-//      */
-//     public static final String TARGET_ID_MEMBERS_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".members"; //$NON-NLS-1$ 
-//     
+       /**
+        * Type hierarchy view part: pop-up menu target ID for type hierarchy viewer
+        * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.typehierarchy"</code>).
+        * 
+        * @since 2.0
+        */
+       public static final String TARGET_ID_HIERARCHY_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".typehierarchy"; //$NON-NLS-1$ 
+
+       /**
+        * Type hierarchy view part: pop-up menu target ID for supertype hierarchy viewer
+        * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.supertypes"</code>).
+        * 
+        * @since 2.0
+        */
+       public static final String TARGET_ID_SUPERTYPES_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".supertypes"; //$NON-NLS-1$   
+
+       /**
+        * Type hierarchy view part: Pop-up menu target ID for the subtype hierarchy viewer
+        * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.subtypes"</code>).
+        * 
+        * @since 2.0
+        */
+       public static final String TARGET_ID_SUBTYPES_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".subtypes"; //$NON-NLS-1$       
+
+       /**
+        * Type hierarchy view part: pop-up menu target ID for the meber viewer
+        * (value <code>"org.eclipse.jdt.ui.TypeHierarchy.members"</code>).
+        * 
+        * @since 2.0
+        */
+       public static final String TARGET_ID_MEMBERS_VIEW= JavaUI.ID_TYPE_HIERARCHY + ".members"; //$NON-NLS-1$ 
+       
 
        /**
         * Pop-up menu: name of group for goto actions (value <code>"group.open"</code>).
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/ITypeHierarchyViewPart.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/ui/ITypeHierarchyViewPart.java
new file mode 100644 (file)
index 0000000..d1c1084
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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 net.sourceforge.phpdt.ui;
+
+
+import org.eclipse.ui.IViewPart;
+
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IType;
+
+/**
+ * The standard type hierarchy view presents a type hierarchy for a given input class
+ * or interface. Visually, this view consists of a pair of viewers, one showing the type
+ * hierarchy, the other showing the members of the type selected in the first.
+ * <p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ *
+ * @see JavaUI#ID_TYPE_HIERARCHY
+ */
+public interface ITypeHierarchyViewPart extends IViewPart {
+
+       /**
+        * Sets the input element of this type hierarchy view to a type.
+        *
+        * @param type the input element of this type hierarchy view, or <code>null</code>
+        *  to clear any input element
+        * @deprecated use setInputElement instead
+        */
+       public void setInput(IType type);
+       
+       /**
+        * Sets the input element of this type hierarchy view. The following input types are possible
+        * <code>IMember</code> (types, methods, fields..), <code>IPackageFragment</code>, <code>IPackageFragmentRoot</code>
+        * and <code>IJavaProject</code>.
+        *
+        * @param element the input element of this type hierarchy view, or <code>null</code>
+        *  to clear any input
+        * 
+        * @since 2.0
+        */
+       public void setInputElement(IJavaElement element);      
+
+       /**
+        * Returns the input element of this type hierarchy view.
+        *
+        * @return the input element, or <code>null</code> if no input element is set
+        * @see #setInput(IType)
+        * @deprecated use getInputElement instead
+        */
+       public IType getInput();
+       
+
+       /**
+        * Returns the input element of this type hierarchy view.
+        *
+        * @return the input element, or <code>null</code> if no input element is set
+        * @see #setInputElement(IJavaElement)
+        * 
+        * @since 2.0
+        */
+       public IJavaElement getInputElement();  
+}
index 84b9c32..5c3b4e8 100644 (file)
@@ -148,7 +148,7 @@ public final class JavaUI {
         * @see org.eclipse.ui.IWorkbenchPage#findView(java.lang.String)
         * @see org.eclipse.ui.IWorkbenchPage#showView(java.lang.String)
         */ 
-//     public static final String ID_TYPE_HIERARCHY=           "org.eclipse.jdt.ui.TypeHierarchy"; //$NON-NLS-1$
+       public static final String ID_TYPE_HIERARCHY=           "net.sourceforge.phpdt.ui.TypeHierarchy"; //$NON-NLS-1$
 
        /**
         * The id of the Java Browsing Perspective
index 814b2e5..61c802a 100644 (file)
@@ -120,7 +120,7 @@ public class PHPeclipsePlugin extends AbstractUIPlugin implements IPreferenceCon
    * The id of the PHP plugin (value <code>"net.sourceforge.phpeclipse"</code>).
    */
   public static final String PLUGIN_ID = "net.sourceforge.phpeclipse"; //$NON-NLS-1$
-
+IWorkspace w;
   /**
    * id of builder - matches plugin.xml (concatenate pluginid.builderid)
    */
index 56229b2..ac33467 100644 (file)
@@ -1318,7 +1318,7 @@ public class PHPUnitEditor extends PHPEditor { //implements
   private final static String ADD_JAVADOC_TAGS = PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS;
 
   /** Preference key for automatically formatting phpdocs */
-  private final static String FORMAT_JAVADOCS = PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
+//  private final static String FORMAT_JAVADOCS = PreferenceConstants.EDITOR_FORMAT_JAVADOCS;
 
   /** Preference key for automatically closing strings */
   private final static String CLOSE_STRINGS_HTML = PreferenceConstants.EDITOR_CLOSE_STRINGS_HTML;
index 5ef32d3..88ed120 100644 (file)
@@ -17,7 +17,7 @@ import java.util.ResourceBundle;
 
 public class PHPWizardMessages {
 
-       private static final String RESOURCE_BUNDLE= "net.sourceforge.phpeclipse.wizards.PHPWizardMessages";//$NON-NLS-1$
+       private static final String RESOURCE_BUNDLE= PHPWizardMessages.class.getName();//$NON-NLS-1$
 
        private static ResourceBundle fgResourceBundle= ResourceBundle.getBundle(RESOURCE_BUNDLE);