public String validate() {
    String message = null;

    switch (entryKind) {
      case IIncludePathEntry.IPE_PROJECT:
        if (resource == null || !resource.exists()) {
          message = CoreMessages.getString("IncludePathEntry_4") + path.toOSString(); // $NON-NLS-1$
        }
        break;
      case IIncludePathEntry.IPE_LIBRARY:
      case IIncludePathEntry.IPE_JRE:
        if (resource == null || !resource.exists()) {
          File file = new File(path.toOSString());
          if (!file.exists()) {
            message =
                CoreMessages.getString("IncludePathEntry_5") + path.toOSString(); // $NON-NLS-1$
          }
        }
        break;
      case IIncludePathEntry.IPE_SOURCE:
        if (resource == null || !resource.exists()) {
          message = CoreMessages.getString("IncludePathEntry_6") + path.toOSString(); // $NON-NLS-1$
        }
        break;
      case IIncludePathEntry.IPE_VARIABLE:
        // if (resource == null || !resource.exists())
        // message = "included variable not found: " + path.toOSString();
        break;
      case IIncludePathEntry.IPE_CONTAINER:
        break;
      default:
        throw new AssertionError(
            NLS.bind(
                CoreMessages.getString("includePath_unknownKind"),
                StringUtil.EMPTY)); // $NON-NLS-1$
    }
    return message;
  }
  public static IIncludePathEntry getEntry(
      String sPath,
      String sEntryKind,
      String sContentKind,
      String sResource,
      boolean isExported,
      IPath projectPath) {
    if (sPath == null
        || sEntryKind == null
        || sContentKind == null
        || sResource == null
        || projectPath == null) {
      throw new IllegalArgumentException("Null arguments are not allowed"); // $NON-NLS-1$
    }
    // ensure path is absolute
    IPath path = new Path(sPath);
    int entryKind = entryKindFromString(sEntryKind);
    if (entryKind != IIncludePathEntry.IPE_VARIABLE
        && entryKind != IIncludePathEntry.IPE_CONTAINER
        && !path.isAbsolute()) {
      path = projectPath.append(path);
    }
    IResource resource = null;

    // recreate the CP entry
    IIncludePathEntry entry = null;
    switch (entryKind) {
      case IIncludePathEntry.IPE_PROJECT:
        try {
          resource = ResourcesPlugin.getWorkspace().getRoot().getProject(sResource);
        } catch (Exception e) {
          // Do nothing
        }
        entry = newProjectEntry(path, resource, isExported);
        break;
      case IIncludePathEntry.IPE_LIBRARY:
      case IIncludePathEntry.IPE_JRE:
        entry =
            new IncludePathEntry(
                contentKindFromString(sContentKind),
                IIncludePathEntry.IPE_LIBRARY,
                path,
                resource,
                isExported);
        break;
      case IIncludePathEntry.IPE_SOURCE:
        // must be an entry in this project or specify another project
        entry = newSourceEntry(path, resource);
        break;
      case IIncludePathEntry.IPE_VARIABLE:
        entry = newVariableEntry(path, resource, isExported);
        break;
      case IIncludePathEntry.IPE_CONTAINER:
        entry = newContainerEntry(path, resource, isExported);
        break;
      default:
        throw new AssertionError(
            NLS.bind(CoreMessages.getString("includePath_unknownKind"), sEntryKind));
    }
    return entry;
  }
  public static void updateProjectReferences(
      IIncludePathEntry[] newEntries,
      IIncludePathEntry[] oldEntries,
      final IProject project,
      SubProgressMonitor monitor) {
    try {
      boolean changedReferences = false;
      final IProjectDescription projectDescription = project.getDescription();
      List<IProject> referenced = new ArrayList<IProject>();
      List<String> referencedNames = new ArrayList<String>();
      IProject[] referencedProjects = projectDescription.getReferencedProjects();
      for (IProject refProject : referencedProjects) {
        referenced.add(refProject);
        referencedNames.add(refProject.getName());
      }

      for (IIncludePathEntry oldEntry : oldEntries) {
        if (oldEntry.getEntryKind() == IIncludePathEntry.IPE_PROJECT) {
          String projectName = oldEntry.getPath().lastSegment();
          if (!containsProject(newEntries, projectName)) {
            if (((IncludePathEntry) oldEntry).createdReference) {
              int index = referencedNames.indexOf(projectName);
              if (index >= 0) {
                changedReferences = true;
                referencedNames.remove(index);
                referenced.remove(index);
              }
            }
          }
        }
      }

      for (IIncludePathEntry newEntry : newEntries) {
        if (newEntry.getEntryKind() == IIncludePathEntry.IPE_PROJECT) {
          String projectName = newEntry.getPath().lastSegment();
          if (!containsProject(oldEntries, projectName)) {
            if (!referencedNames.contains(projectName)) {
              changedReferences = true;
              ((IncludePathEntry) newEntry).createdReference = true;
              referenced.add(ResourcesPlugin.getWorkspace().getRoot().getProject(projectName));
              referencedNames.add(projectName);
            }
          }
        }
      }
      if (changedReferences) {
        IProject[] referenceProjects =
            (IProject[]) referenced.toArray(new IProject[referenced.size()]);
        projectDescription.setReferencedProjects(referenceProjects);
        WorkspaceJob job =
            new WorkspaceJob(CoreMessages.getString("IncludePathEntry_2")) // $NON-NLS-1$
            {
              public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
                project.setDescription(projectDescription, monitor);
                return Status.OK_STATUS;
              }
            };
        job.setRule(project.getParent());
        job.schedule();
      }
    } catch (CoreException e) {
      PHPEplPlugin.logError(e);
    }
  }
/**
 * A base class for all the occurrence finders.
 *
 * @author shalom
 */
public abstract class AbstractOccurrencesFinder extends AbstractVisitor
    implements IOccurrencesFinder {

  public static final char NAMESPACE_SEPARATOR = '\\';

  protected static final String BASE_DESCRIPTION =
      CoreMessages.getString("AbstractOccurrencesFinder.0"); // $NON-NLS-1$
  protected static final String BASE_WRITE_DESCRIPTION =
      CoreMessages.getString("AbstractOccurrencesFinder.1"); // $NON-NLS-1$
  protected static final String BRACKETS = "()"; // $NON-NLS-1$

  protected List<OccurrenceLocation> fResult;
  protected String fDescription;
  protected Program fASTRoot;
  protected ProblemDesc[] fProblems;

  protected NamespaceDeclaration fCurrentNamespace;
  protected Map<String, UseStatementPart> fLastUseParts = new HashMap<String, UseStatementPart>();

  static class ProblemDesc {
    int kind;
    int offset;
    int end;
    int severity;

    public ProblemDesc(int kind, int offset, int end, int severity) {
      this.kind = kind;
      this.offset = offset;
      this.end = end;
      this.severity = severity;
    }

    public boolean isError() {
      // return (this.severity & ProblemSeverities.Error) != 0;
      return (this.severity == 1);
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org2.eclipse.php.internal.ui.search.IOccurrencesFinder#initialize(org.
   * eclipse.php.internal.core.ast.nodes.Program, int, int)
   */
  public String initialize(Program root, int offset, int length) {
    return initialize(root, NodeFinder.perform(root, offset, length));
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org2.eclipse.php.internal.ui.search.IOccurrencesFinder#getOccurrences()
   */
  public OccurrenceLocation[] getOccurrences() {
    fResult = new ArrayList<OccurrenceLocation>();
    findOccurrences();
    if (fResult.isEmpty()) return null;

    return fResult.toArray(new OccurrenceLocation[fResult.size()]);
  }

  /**
   * Returns all problems in this program
   *
   * @param node
   * @return
   */
  public static ProblemDesc[] getProblems(Program node) {
    try {
      if (node.getSourceModule() == null) {
        return null;
      }

      Object resource = node.getSourceModule().getResource();
      if (resource != null) {
        IMarker[] markers = null;

        if (resource instanceof IResource) {
          markers =
              ((IResource) resource)
                  .findMarkers(DefaultProblem.MARKER_TYPE_PROBLEM, true, IResource.DEPTH_ONE);
        } else if (resource instanceof IUniformResource) {
          markers =
              MarkerUtils.findMarkers(
                  (IUniformResource) resource, DefaultProblem.MARKER_TYPE_PROBLEM, true);
        }
        if (markers == null) {
          return null;
        }
        ProblemDesc[] problems = new ProblemDesc[markers.length];
        for (int i = 0; i < markers.length; ++i) {
          problems[i] =
              new ProblemDesc(
                  markers[i].getAttribute(
                      "id", //$NON-NLS-1$
                      0),
                  markers[i].getAttribute(IMarker.CHAR_START, 0),
                  markers[i].getAttribute(IMarker.CHAR_END, 0),
                  markers[i].getAttribute(IMarker.SEVERITY, 0));
        }
        return problems;
      }
    } catch (CoreException e) {
    }
    return null;
  }

  /**
   * Whether the specified source range contains error
   *
   * @param offset
   * @param end
   * @return
   */
  protected boolean hasProblems(int offset, int end) {
    if (fProblems != null) {
      // Check that current location doesn't contain errors
      for (ProblemDesc problemDesc : fProblems) {
        if (problemDesc.offset <= offset && problemDesc.end >= end) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Adds occurrence to results list in case there's no error in this position
   *
   * @param location Occurrence location
   */
  protected void addOccurrence(OccurrenceLocation location) {
    if (!hasProblems(location.getOffset(), location.getOffset() + location.getLength())) {
      fResult.add(location);
    }
  }

  /**
   * Find and add all the occurrences. Extending finders must implement this method to fill the
   * results list. Note that this method should not be called directly. It is being called by the
   * {@link #getOccurrences()}.
   *
   * @see #getOccurrences()
   */
  protected abstract void findOccurrences();

  /**
   * Returns the type of this occurrence.
   *
   * @param node The {@link ASTNode} to check.
   * @return The occurrence type (one of {@link IOccurrencesFinder} type constants)
   * @see IOccurrencesFinder
   */
  protected abstract int getOccurrenceType(ASTNode node);

  /*
   * (non-Javadoc)
   *
   * @see org2.eclipse.php.internal.ui.search.IOccurrencesFinder#getASTRoot()
   */
  public Program getASTRoot() {
    return fASTRoot;
  }

  /*
   * (non-Javadoc)
   *
   * @see org2.eclipse.php.internal.ui.search.IOccurrencesFinder#getJobLabel()
   */
  public String getJobLabel() {
    return "OccurrencesFinder_job_label"; //$NON-NLS-1$
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * org2.eclipse.php.internal.ui.search.IOccurrencesFinder#getSearchKind()
   */
  public int getSearchKind() {
    return IOccurrencesFinder.K_OCCURRENCE;
  }

  /*
   * (non-Javadoc)
   *
   * @see org2.eclipse.php.internal.ui.search.IOccurrencesFinder#
   * getUnformattedPluralLabel()
   */
  public String getUnformattedPluralLabel() {
    return "OccurrencesFinder_label_plural"; //$NON-NLS-1$
  }

  /*
   * (non-Javadoc)
   * @see org2.eclipse.php.internal.ui.search.IOccurrencesFinder# getUnformattedSingularLabel()
   */
  public String getUnformattedSingularLabel() {
    return "OccurrencesFinder_label_singular"; //$NON-NLS-1$
  }

  public boolean visit(NamespaceDeclaration namespaceDeclaration) {
    fCurrentNamespace = namespaceDeclaration;
    fLastUseParts.clear();
    return true;
  }

  public void endVisit(NamespaceDeclaration namespaceDeclaration) {
    fCurrentNamespace = null;
    fLastUseParts.clear();
  }

  public boolean visit(UseStatement useStatement) {
    List<UseStatementPart> useParts = useStatement.parts();
    for (UseStatementPart part : useParts) {
      String name = null;
      if (part.getAlias() != null) {
        name = part.getAlias().getName();
      } else {
        name = part.getName().getName();
        int index = name.lastIndexOf(NAMESPACE_SEPARATOR);
        if (index >= 0) {
          name = name.substring(index + 1);
        }
      }
      fLastUseParts.put(name, part);
    }
    return true;
  }

  public static String getFullName(
      Identifier identifier,
      Map<String, UseStatementPart> lastUseParts,
      NamespaceDeclaration currentNamespace) {
    return getFullName(identifier.getName(), lastUseParts, currentNamespace);
  }

  public static String getFullName(
      String fullName,
      Map<String, UseStatementPart> lastUseParts,
      NamespaceDeclaration currentNamespace) {
    if (fullName.charAt(0) != NAMESPACE_SEPARATOR) {
      int index = fullName.lastIndexOf(NAMESPACE_SEPARATOR);
      if (index >= 0) {
        String namespace = fullName.substring(0, index);
        if (lastUseParts.containsKey(namespace)) {
          fullName =
              new StringBuilder(lastUseParts.get(namespace).getName().getName())
                  .append(NAMESPACE_SEPARATOR)
                  .append(fullName.substring(index + 1))
                  .toString();
        }
      } else if (lastUseParts.containsKey(fullName)) {
        fullName = new StringBuilder(lastUseParts.get(fullName).getName().getName()).toString();
      } else {
        if (currentNamespace != null && currentNamespace.getName() != null) {
          fullName =
              new StringBuilder(currentNamespace.getName().getName())
                  .append(NAMESPACE_SEPARATOR)
                  .append(fullName)
                  .toString();
        }
      }
    }
    if (fullName.charAt(0) == NAMESPACE_SEPARATOR) {
      fullName = fullName.substring(1);
    }
    return fullName;
  }
}