/**
   * Add an element to the script search scope.
   *
   * @param element The element we want to add to current script search scope
   * @throws ModelException May happen if some Script Model info are not available
   */
  public void add(IModelElement element) throws ModelException {
    if (!natureFilter(element)) {
      return;
    }
    IPath containerPath = null;
    String containerPathToString = null;
    int includeMask = SOURCES | APPLICATION_LIBRARIES | SYSTEM_LIBRARIES;
    switch (element.getElementType()) {
      case IModelElement.SCRIPT_MODEL:
        // a workspace scope should be used
        break;
      case IModelElement.SCRIPT_PROJECT:
        add((ScriptProject) element, null, includeMask, new HashSet<IProject>(2), null);
        break;
      case IModelElement.PROJECT_FRAGMENT:
        IProjectFragment root = (IProjectFragment) element;
        String projectPath = null;
        if (!root.isExternal()) {
          IPath rootPath = root.getPath();
          containerPath =
              root.getKind() == IProjectFragment.K_SOURCE ? root.getParent().getPath() : rootPath;
          containerPathToString = containerPath.toString();
          IResource rootResource = root.getResource();
          projectPath = root.getScriptProject().getPath().toString();
          if (rootResource != null && rootResource.isAccessible()) {
            String relativePath =
                Util.relativePath(rootResource.getFullPath(), containerPath.segmentCount());
            add(projectPath, relativePath, containerPathToString, false /* not a package */, null);
          } else {
            add(
                projectPath,
                org.eclipse.dltk.compiler.util.Util.EMPTY_STRING,
                containerPathToString,
                false /* not a package */,
                null);
          }
        } else {
          projectPath = root.getScriptProject().getPath().toString();
          containerPath = root.getPath();
          containerPathToString = containerPath.toString();
          add(
              projectPath,
              org.eclipse.dltk.compiler.util.Util.EMPTY_STRING,
              containerPathToString,
              false /* not a package */,
              null);
        }
        break;
      case IModelElement.SCRIPT_FOLDER:
        root = (IProjectFragment) element.getParent();
        projectPath = root.getScriptProject().getPath().toString();
        if (root.isArchive()) {
          if (DLTKCore.DEBUG) {
            System.err.println("TODO: Check. Bug possible..."); // $NON-NLS-1$
          }
          String relativePath = ((ModelElement) element).getPath().toString() + '/';
          containerPath = root.getPath();
          containerPathToString = containerPath.toString();
          add(projectPath, relativePath, containerPathToString, true /* package */, null);
        } else {
          IResource resource = element.getResource();
          if (resource != null) {
            if (resource.isAccessible()) {
              containerPath =
                  root.getKind() == IProjectFragment.K_SOURCE
                      ? root.getParent().getPath()
                      : root.getPath();
            } else {
              // for working copies, get resource container full path
              containerPath = resource.getParent().getFullPath();
            }
            containerPathToString = containerPath.toString();
            String relativePath =
                Util.relativePath(resource.getFullPath(), containerPath.segmentCount());
            add(projectPath, relativePath, containerPathToString, true /* package */, null);
          }
        }
        break;
      default:
        // remember sub-cu (or sub-class file) script elements
        if (element instanceof IMember) {
          if (this.elements == null) {
            this.elements = new ArrayList<IModelElement>();
          }
          this.elements.add(element);
        }
        root = (IProjectFragment) element.getAncestor(IModelElement.PROJECT_FRAGMENT);
        projectPath = root.getScriptProject().getPath().toString();
        String relativePath;
        if (root.getKind() == IProjectFragment.K_SOURCE && !root.isExternal()) {
          containerPath = root.getParent().getPath();
          relativePath = Util.relativePath(getPath(element, false /* full path */), 1 /*
																				 * remove
																				 * project
																				 * segmet
																				 */);
        } else {
          containerPath = root.getPath();
          relativePath = getPath(element, true /* relative path */).toString();
        }
        containerPathToString = containerPath.toString();
        add(projectPath, relativePath, containerPathToString, false /*
																		 * not a
																		 * package
																		 */, null);
    }

    if (containerPath != null) addEnclosingProjectOrArchive(containerPath);
  }
  /**
   * Processes a delta recursively. When more than two children are affected the tree is fully
   * refreshed starting at this node.
   *
   * @param delta the delta to process
   * @param runnables the resulting view changes as runnables (type {@link Runnable} )
   * @return true is returned if the conclusion is to refresh a parent of an element. In that case
   *     no siblings need to be processed
   * @throws JavaModelException thrown when the access to an element failed
   */
  private boolean processDelta(final IModelElementDelta delta, final Collection<Runnable> runnables)
      throws ModelException {

    int kind = delta.getKind();
    int flags = delta.getFlags();
    IModelElement element = delta.getElement();
    int elementType = element.getElementType();

    if (elementType != IModelElement.SCRIPT_MODEL && elementType != IModelElement.SCRIPT_PROJECT) {
      IScriptProject proj = element.getScriptProject();
      if (proj == null || !proj.getProject().isOpen()) {
        // TODO: Not needed if parent already did the 'open' check!
        return false;
      }
    }

    if (elementType == IModelElement.SCRIPT_FOLDER) {
      if ((flags & (IModelElementDelta.F_CONTENT | IModelElementDelta.F_CHILDREN))
          == IModelElementDelta.F_CONTENT) {
        if (!fIsFlatLayout) {
          Object parent = getHierarchicalPackageParent((IScriptFolder) element);
          if (!(parent instanceof IProjectFragment)) {
            postRefresh(internalGetParent(parent), GRANT_PARENT, element, runnables);
            return true;
          }
        }
        // content change, without children info (for example resource
        // added/removed to class folder package)
        postRefresh(internalGetParent(element), PARENT, element, runnables);
        return true;
      }

      if (!fIsFlatLayout) {
        if (kind == IModelElementDelta.REMOVED) {
          final Object parent = getHierarchicalPackageParent((IScriptFolder) element);
          if (parent instanceof IProjectFragment) {
            postRemove(element, runnables);
            return false;
          } else {
            postRefresh(internalGetParent(parent), GRANT_PARENT, element, runnables);
            return true;
          }
        } else if (kind == IModelElementDelta.ADDED) {
          final Object parent = getHierarchicalPackageParent((IScriptFolder) element);
          if (parent instanceof IProjectFragment) {
            if (fFoldPackages) {
              postRefresh(parent, PARENT, element, runnables);
              return true;
            } else {
              postAdd(parent, element, runnables);
              return false;
            }
          } else {
            postRefresh(internalGetParent(parent), GRANT_PARENT, element, runnables);
            return true;
          }
        }
        handleAffectedChildren(delta, element, runnables);
        return false;
      }
    }

    if (elementType == IModelElement.SOURCE_MODULE) {
      ISourceModule cu = (ISourceModule) element;
      if (!ScriptModelUtil.isPrimary(cu)) {
        return false;
      }

      if (!getProvideMembers() && cu.isWorkingCopy() && kind == IModelElementDelta.CHANGED) {
        return false;
      }

      if (kind == IModelElementDelta.CHANGED && !isStructuralCUChange(flags)) {
        return false; // test moved ahead
      }

      if (!isOnClassPath(cu)) { // TODO: isOnClassPath expensive! Should
        // be put after all cheap tests
        return false;
      }
    }

    if (elementType == IModelElement.SCRIPT_PROJECT) {
      // handle open and closing of a project
      if ((flags & (IModelElementDelta.F_CLOSED | IModelElementDelta.F_OPENED)) != 0) {
        postRefresh(element, ORIGINAL, element, runnables);
        return false;
      }
      // if the class path has changed we refresh the entire project
      if ((flags & IModelElementDelta.F_BUILDPATH_CHANGED) != 0) {
        postRefresh(element, ORIGINAL, element, runnables);
        return false;
      }
      // if added it could be that the corresponding IProject is already
      // shown. Remove it first.
      // bug 184296
      if (kind == IModelElementDelta.ADDED) {
        postRemove(element.getResource(), runnables);
        postAdd(element.getParent(), element, runnables);
        return false;
      }
    }

    if (kind == IModelElementDelta.REMOVED) {
      Object parent = internalGetParent(element);
      if (element instanceof IScriptFolder) {
        // refresh package fragment root to allow filtering empty
        // (parent) packages: bug 72923
        if (fViewer.testFindItem(parent) != null) {
          postRefresh(parent, PARENT, element, runnables);
        }
        return true;

      } else if (element instanceof IProjectFragment
          && ((IProjectFragment) element).getKind() != IProjectFragment.K_SOURCE) {
        // libs and class folders can show up twice (in library
        // container and as resource at original location)
        IResource resource = element.getResource();
        if (resource != null) postRemove(resource, runnables);
      }

      postRemove(element, runnables);
      if (parent instanceof IScriptFolder) {
        postUpdateIcon((IScriptFolder) parent, runnables);
      }
      // we are filtering out empty subpackages, so we
      // a package becomes empty we remove it from the viewer.
      if (isScriptFolderEmpty(element.getParent())) {
        if (fViewer.testFindItem(parent) != null) {
          postRefresh(internalGetParent(parent), GRANT_PARENT, element, runnables);
        }
        return true;
      }
      return false;
    }

    if (kind == IModelElementDelta.ADDED) {
      Object parent = internalGetParent(element);
      // we are filtering out empty subpackages, so we
      // have to handle additions to them specially.
      if (parent instanceof IScriptFolder) {
        Object grandparent = internalGetParent(parent);
        // 1GE8SI6: ITPJUI:WIN98 - Rename is not shown in Packages View
        // avoid posting a refresh to an invisible parent
        if (parent.equals(fInput)) {
          postRefresh(parent, PARENT, element, runnables);
        } else {
          // refresh from grandparent if parent isn't visible yet
          if (fViewer.testFindItem(parent) == null) {
            postRefresh(grandparent, GRANT_PARENT, element, runnables);
          } else {
            postRefresh(parent, PARENT, element, runnables);
          }
        }
        return true;
      } else {
        postAdd(parent, element, runnables);
      }
    }

    if (elementType == IModelElement.SOURCE_MODULE || elementType == IModelElement.BINARY_MODULE) {
      if (kind == IModelElementDelta.CHANGED) {
        // isStructuralCUChange already performed above
        postRefresh(element, ORIGINAL, element, runnables);
      }
      return false;
    }

    if (elementType == IModelElement.PROJECT_FRAGMENT) {
      // the contents of an external JAR or class folder has changed
      if ((flags & IModelElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) {
        postRefresh(element, ORIGINAL, element, runnables);
        return false;
      }
      if ((flags & (IModelElementDelta.F_CONTENT | IModelElementDelta.F_CHILDREN))
          == IModelElementDelta.F_CONTENT) {
        // content change, without children info (for example resource
        // added/removed to class folder package)
        postRefresh(internalGetParent(element), PARENT, element, runnables);
        return true;
      }
      // the source attachment of a JAR has changed
      // if ((flags & ( | IModelElementDelta.F_SOURCEDETACHED)) != 0) {
      // postUpdateIcon(element, runnables);
      // }

      if (isBuildPathChange(delta)) {
        // throw the towel and do a full refresh of the affected java
        // project.
        postRefresh(element.getScriptProject(), PROJECT, element, runnables);
        return true;
      }
    }

    handleAffectedChildren(delta, element, runnables);
    return false;
  }