/**
  * Validate the given Java identifier for the given source and compliance levels The identifier
  * must not have the same spelling as a Java keyword, boolean literal (<code>"true"</code>, <code>
  * "false"</code>), or null literal (<code>"null"</code>). See section 3.8 of the <em>Java
  * Language Specification, Second Edition</em> (JLS2). A valid identifier can act as a simple type
  * name, method name or field name.
  *
  * @param id the Java identifier
  * @param sourceLevel the source level
  * @param complianceLevel the compliance level
  * @return a status object with code <code>IStatus.OK</code> if the given identifier is a valid
  *     Java identifier, otherwise a status object indicating what is wrong with the identifier
  * @since 3.3
  */
 public static IStatus validateIdentifier(String id, String sourceLevel, String complianceLevel) {
   if (scannedIdentifier(id, sourceLevel, complianceLevel) != null) {
     return JavaModelStatus.VERIFIED_OK;
   } else {
     return new Status(
         IStatus.ERROR,
         JavaCore.PLUGIN_ID,
         -1,
         Messages.bind(Messages.convention_illegalIdentifier, id),
         null);
   }
 }
  /**
   * Validate the given Java type name, either simple or qualified, for the given source and
   * compliance levels.
   *
   * <p>For example, <code>"java.lang.Object"</code>, or <code>"Object"</code>.
   *
   * <p>The source level and compliance level values should be taken from the constant defined
   * inside {@link JavaCore} class. The constants are named <code>JavaCore#VERSION_1_x</code>, x
   * being set between '1' and '8'.
   *
   * @param name the name of a type
   * @param sourceLevel the source level
   * @param complianceLevel the compliance level
   * @return a status object with code <code>IStatus.OK</code> if the given name is valid as a Java
   *     type name, a status with code <code>IStatus.WARNING</code> indicating why the given name is
   *     discouraged, otherwise a status object indicating what is wrong with the name
   * @since 3.3
   * @see JavaCore#VERSION_1_1
   * @see JavaCore#VERSION_1_2
   * @see JavaCore#VERSION_1_3
   * @see JavaCore#VERSION_1_4
   * @see JavaCore#VERSION_1_5
   * @see JavaCore#VERSION_1_6
   * @see JavaCore#VERSION_1_7
   * @see JavaCore#VERSION_1_8
   */
  public static IStatus validateJavaTypeName(
      String name, String sourceLevel, String complianceLevel) {
    if (name == null) {
      return new Status(
          IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null);
    }
    String trimmed = name.trim();
    if (!name.equals(trimmed)) {
      return new Status(
          IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_type_nameWithBlanks, null);
    }
    int index = name.lastIndexOf('.');
    char[] scannedID;
    if (index == -1) {
      // simple name
      scannedID = scannedIdentifier(name, sourceLevel, complianceLevel);
    } else {
      // qualified name
      String pkg = name.substring(0, index).trim();
      IStatus status = validatePackageName(pkg, sourceLevel, complianceLevel);
      if (!status.isOK()) {
        return status;
      }
      String type = name.substring(index + 1).trim();
      scannedID = scannedIdentifier(type, sourceLevel, complianceLevel);
    }

    if (scannedID != null) {
      IStatus status =
          ResourcesPlugin.getWorkspace().validateName(new String(scannedID), IResource.FILE);
      if (!status.isOK()) {
        return status;
      }
      if (CharOperation.contains('$', scannedID)) {
        return new Status(
            IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_type_dollarName, null);
      }
      if ((scannedID.length > 0 && ScannerHelper.isLowerCase(scannedID[0]))) {
        return new Status(
            IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_type_lowercaseName, null);
      }
      return JavaModelStatus.VERIFIED_OK;
    } else {
      return new Status(
          IStatus.ERROR,
          JavaCore.PLUGIN_ID,
          -1,
          Messages.bind(Messages.convention_type_invalidName, name),
          null);
    }
  }
  /**
   * Validate the given package name for the given source and compliance levels.
   *
   * <p>The syntax of a package name corresponds to PackageName as defined by PackageDeclaration
   * (JLS2 7.4). For example, <code>"java.lang"</code>.
   *
   * <p>Note that the given name must be a non-empty package name (that is, attempting to validate
   * the default package will return an error status.) Also it must not contain any characters or
   * substrings that are not valid on the file system on which workspace root is located.
   *
   * @param name the name of a package
   * @param sourceLevel the source level
   * @param complianceLevel the compliance level
   * @return a status object with code <code>IStatus.OK</code> if the given name is valid as a
   *     package name, otherwise a status object indicating what is wrong with the name
   * @since 3.3
   */
  public static IStatus validatePackageName(
      String name, String sourceLevel, String complianceLevel) {

    if (name == null) {
      return new Status(
          IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_nullName, null);
    }
    int length;
    if ((length = name.length()) == 0) {
      return new Status(
          IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_emptyName, null);
    }
    if (name.charAt(0) == DOT || name.charAt(length - 1) == DOT) {
      return new Status(
          IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_dotName, null);
    }
    if (CharOperation.isWhitespace(name.charAt(0))
        || CharOperation.isWhitespace(name.charAt(name.length() - 1))) {
      return new Status(
          IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_package_nameWithBlanks, null);
    }
    int dot = 0;
    while (dot != -1 && dot < length - 1) {
      if ((dot = name.indexOf(DOT, dot + 1)) != -1
          && dot < length - 1
          && name.charAt(dot + 1) == DOT) {
        return new Status(
            IStatus.ERROR,
            JavaCore.PLUGIN_ID,
            -1,
            Messages.convention_package_consecutiveDotsName,
            null);
      }
    }
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    StringTokenizer st = new StringTokenizer(name, "."); // $NON-NLS-1$
    boolean firstToken = true;
    IStatus warningStatus = null;
    while (st.hasMoreTokens()) {
      String typeName = st.nextToken();
      typeName = typeName.trim(); // grammar allows spaces
      char[] scannedID = scannedIdentifier(typeName, sourceLevel, complianceLevel);
      if (scannedID == null) {
        return new Status(
            IStatus.ERROR,
            JavaCore.PLUGIN_ID,
            -1,
            Messages.bind(Messages.convention_illegalIdentifier, typeName),
            null);
      }
      IStatus status = workspace.validateName(new String(scannedID), IResource.FOLDER);
      if (!status.isOK()) {
        return status;
      }
      if (firstToken && scannedID.length > 0 && ScannerHelper.isUpperCase(scannedID[0])) {
        if (warningStatus == null) {
          warningStatus =
              new Status(
                  IStatus.WARNING,
                  JavaCore.PLUGIN_ID,
                  -1,
                  Messages.convention_package_uppercaseName,
                  null);
        }
      }
      firstToken = false;
    }
    if (warningStatus != null) {
      return warningStatus;
    }
    return JavaModelStatus.VERIFIED_OK;
  }