/**
  * @param element
  * @param iBuildpathEntry
  * @return the name of the container description
  */
 private String getEntryDescription(Object element, IBuildpathEntry iBuildpathEntry) {
   IProject project = ((IncludePath) element).getProject();
   IScriptProject scriptProject = DLTKCore.create(project);
   IBuildpathContainer buildpathContainer = null;
   try {
     buildpathContainer = DLTKCore.getBuildpathContainer(iBuildpathEntry.getPath(), scriptProject);
   } catch (ModelException e) {
     // no matching container - return the path
   }
   if (buildpathContainer != null) {
     return buildpathContainer.getDescription();
   }
   return iBuildpathEntry.getPath().toOSString();
 }
  /**
   * Returns the transitive closure of buildpath entries for the given project entry.
   *
   * @param projectEntry project buildpath entry
   * @param expandedPath a list of entries already expanded, should be empty to begin, and contains
   *     the result
   * @param expanding a list of projects that have been or are currently being expanded (to detect
   *     cycles)
   * @exception CoreException if unable to expand the buildpath
   */
  private void expandProject(IBuildpathEntry projectEntry, List expandedPath, List expanding)
      throws CoreException {
    expanding.add(projectEntry);
    // 1. Get the raw buildpath
    // 2. Replace source folder entries with a project entry
    IPath projectPath = projectEntry.getPath();
    IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(projectPath.lastSegment());
    if (res == null) {
      // add project entry and return
      expandedPath.add(projectEntry);
      return;
    }
    IScriptProject project = (IScriptProject) DLTKCore.create(res);
    if (project == null || !project.getProject().isOpen() || !project.exists()) {
      // add project entry and return
      expandedPath.add(projectEntry);
      return;
    }

    IBuildpathEntry[] buildPath = project.getRawBuildpath();
    List unexpandedPath = new ArrayList(buildPath.length);
    // boolean projectAdded = false;
    for (int i = 0; i < buildPath.length; i++) {
      IBuildpathEntry buildpathEntry = buildPath[i];
      if (buildpathEntry.getEntryKind() == IBuildpathEntry.BPE_SOURCE) { // sources
        // are
        // always
        // added
        unexpandedPath.add(buildpathEntry);
      } else {
        // add exported entires, as configured
        if (buildpathEntry.isExported()) {
          unexpandedPath.add(buildpathEntry);
        } else if (!isExportedEntriesOnly() || project.equals(getScriptProject())) {
          // add non exported entries from root project or if we are
          // including all entries
          unexpandedPath.add(buildpathEntry);
        }
      }
    }
    // 3. expand each project entry (except for the root project)
    // 4. replace each container entry with a runtime entry associated with
    // the project
    Iterator iter = unexpandedPath.iterator();
    while (iter.hasNext()) {
      IBuildpathEntry entry = (IBuildpathEntry) iter.next();
      if (entry == projectEntry) {
        expandedPath.add(entry);
      } else {
        switch (entry.getEntryKind()) {
          case IBuildpathEntry.BPE_PROJECT:
            if (!expanding.contains(entry)) {
              expandProject(entry, expandedPath, expanding);
            }
            break;
          case IBuildpathEntry.BPE_CONTAINER:
            IBuildpathContainer container =
                DLTKCore.getBuildpathContainer(entry.getPath(), project);
            int property = -1;
            if (container != null) {
              switch (container.getKind()) {
                case IBuildpathContainer.K_APPLICATION:
                  property = IRuntimeBuildpathEntry.USER_ENTRY;
                  break;
                case IBuildpathContainer.K_DEFAULT_SYSTEM:
                  property = IRuntimeBuildpathEntry.STANDARD_ENTRY;
                  break;
                case IBuildpathContainer.K_SYSTEM:
                  property = IRuntimeBuildpathEntry.BOOTSTRAP_ENTRY;
                  break;
              }
              IRuntimeBuildpathEntry r =
                  ScriptRuntime.newRuntimeContainerBuildpathEntry(
                      entry.getPath(), property, project);
              // check for duplicate/redundant entries
              boolean duplicate = false;
              BuildpathContainerInitializer initializer =
                  DLTKCore.getBuildpathContainerInitializer(r.getPath().segment(0));
              for (int i = 0; i < expandedPath.size(); i++) {
                Object o = expandedPath.get(i);
                if (o instanceof IRuntimeBuildpathEntry) {
                  IRuntimeBuildpathEntry re = (IRuntimeBuildpathEntry) o;
                  if (re.getType() == IRuntimeBuildpathEntry.CONTAINER) {
                    BuildpathContainerInitializer initializer2 =
                        DLTKCore.getBuildpathContainerInitializer(re.getPath().segment(0));
                    Object id1 = null;
                    Object id2 = null;
                    if (initializer == null) {
                      id1 = r.getPath().segment(0);
                    } else {
                      id1 = initializer.getComparisonID(r.getPath(), project);
                    }
                    if (initializer2 == null) {
                      id2 = re.getPath().segment(0);
                    } else {
                      IScriptProject context = re.getScriptProject();
                      if (context == null) {
                        context = project;
                      }
                      id2 = initializer2.getComparisonID(re.getPath(), context);
                    }
                    if (id1 == null) {
                      duplicate = id2 == null;
                    } else {
                      duplicate = id1.equals(id2);
                    }
                    if (duplicate) {
                      break;
                    }
                  }
                }
              }
              if (!duplicate) {
                expandedPath.add(r);
              }
            }
            break;
          default:
            if (!expandedPath.contains(entry)) {
              expandedPath.add(entry);
            }
            break;
        }
      }
    }
    return;
  }
  /**
   * Add a path to current script search scope or all project fragment roots if null. Use project
   * resolved classpath to retrieve and store access restriction on each classpath entry. Recurse if
   * dependent projects are found.
   *
   * @param scriptProject Project used to get resolved classpath entries
   * @param pathToAdd Path to add in case of single element or null if user want to add all project
   *     package fragment roots
   * @param includeMask Mask to apply on buildpath entries
   * @param visitedProjects Set to avoid infinite recursion
   * @param referringEntry Project raw entry in referring project buildpath
   * @throws ModelException May happen while getting script model info
   */
  void add(
      ScriptProject scriptProject,
      IPath pathToAdd,
      int includeMask,
      HashSet<IProject> visitedProjects,
      IBuildpathEntry referringEntry)
      throws ModelException {
    if (!natureFilter(scriptProject)) {
      return;
    }
    IProject project = scriptProject.getProject();
    if (!project.isAccessible() || !visitedProjects.add(project)) return;

    IPath projectPath = project.getFullPath();
    String projectPathString = projectPath.toString();
    this.addEnclosingProjectOrArchive(projectPath);

    // Iterate via project fragments without buildpath entries
    IProjectFragment[] fragments = scriptProject.getProjectFragments();
    for (int i = 0; i < fragments.length; i++) {
      if (fragments[i].getRawBuildpathEntry() == null) {
        add(fragments[i]);
      }
    }

    IBuildpathEntry[] entries = scriptProject.getResolvedBuildpath();
    IScriptModel model = scriptProject.getModel();
    ModelManager.PerProjectInfo perProjectInfo = scriptProject.getPerProjectInfo();
    for (int i = 0, length = entries.length; i < length; i++) {
      IBuildpathEntry entry = entries[i];
      AccessRuleSet access = null;
      BuildpathEntry cpEntry = (BuildpathEntry) entry;
      if (referringEntry != null) {
        // Add only exported entries.
        // Source folder are implicitly exported.
        if (!entry.isExported() && entry.getEntryKind() != IBuildpathEntry.BPE_SOURCE) continue;
        cpEntry = cpEntry.combineWith((BuildpathEntry) referringEntry);
        // cpEntry =
        // ((BuildpathEntry)referringEntry).combineWith(cpEntry);
      }
      access = cpEntry.getAccessRuleSet();
      switch (entry.getEntryKind()) {
        case IBuildpathEntry.BPE_LIBRARY:
          IBuildpathEntry rawEntry = null;
          Map<IPath, IBuildpathEntry> rootPathToRawEntries = perProjectInfo.rootPathToRawEntries;
          if (rootPathToRawEntries != null) {
            rawEntry = rootPathToRawEntries.get(entry.getPath());
          }
          if (rawEntry == null) {
            break;
          }
          switch (rawEntry.getEntryKind()) {
            case IBuildpathEntry.BPE_LIBRARY:
            case IBuildpathEntry.BPE_VARIABLE:
              if ((includeMask & APPLICATION_LIBRARIES) != 0) {
                IPath path = entry.getPath();
                if (pathToAdd == null || pathToAdd.equals(path)) {
                  String pathToString = path.toString();
                  add(
                      projectPath.toString(),
                      "",
                      pathToString,
                      false /* not a package */,
                      access); //$NON-NLS-1$
                  addEnclosingProjectOrArchive(path);
                }
              }
              break;
            case IBuildpathEntry.BPE_CONTAINER:
              IBuildpathContainer container =
                  DLTKCore.getBuildpathContainer(rawEntry.getPath(), scriptProject);
              if (container == null) break;
              if ((container.getKind() == IBuildpathContainer.K_APPLICATION
                      && (includeMask & APPLICATION_LIBRARIES) != 0)
                  || (includeMask & SYSTEM_LIBRARIES) != 0) {
                IPath path = entry.getPath();
                if (pathToAdd == null || pathToAdd.equals(path)) {
                  String pathToString = path.toString();
                  add(
                      projectPath.toString(),
                      "",
                      pathToString,
                      false /* not a package */,
                      access); //$NON-NLS-1$
                  addEnclosingProjectOrArchive(path);
                }
              }
              break;
          }
          break;
        case IBuildpathEntry.BPE_PROJECT:
          if ((includeMask & REFERENCED_PROJECTS) != 0) {
            IPath path = entry.getPath();
            if (pathToAdd == null || pathToAdd.equals(path)) {
              add(
                  (ScriptProject) model.getScriptProject(entry.getPath().lastSegment()),
                  null,
                  includeMask,
                  visitedProjects,
                  cpEntry);
            }
          }
          break;
        case IBuildpathEntry.BPE_SOURCE:
          if ((includeMask & SOURCES) != 0) {
            IPath path = entry.getPath();
            if (pathToAdd == null || pathToAdd.equals(path)) {
              add(
                  projectPath.toString(),
                  Util.relativePath(path, 1 /*
														 * remove project
														 * segment
														 */),
                  projectPathString,
                  false /*
                         * not a package
                         */,
                  access);
            }
          }
          break;
      }
    }
  }