/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.core;

import java.util.StringTokenizer;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.util.Messages;

/**
 * Provides methods for checking Java-specific conventions such as name syntax.
 * <p>
 * This class provides static methods and constants only.
 * </p>
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public final class JavaConventions {

	private static final char DOT= '.';
    private static final Pattern DOT_DOT = Pattern.compile("(\\.)(\\1)+"); //$NON-NLS-1$
    private static final Pattern TERMINAL_DIGIT = Pattern.compile("\\d$"); //$NON-NLS-1$
    private static final Pattern PREFIX_JAVA = Pattern.compile("java$"); //$NON-NLS-1$
	private static final Scanner SCANNER = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);

	private JavaConventions() {
		// Not instantiable
	}

	/**
	 * Returns whether the given package fragment root paths are considered
	 * to overlap.
	 * <p>
	 * Two root paths overlap if one is a prefix of the other, or they point to
	 * the same location. However, a JAR is allowed to be nested in a root.
	 *
	 * @param rootPath1 the first root path
	 * @param rootPath2 the second root path
	 * @return true if the given package fragment root paths are considered to overlap, false otherwise
	 * @deprecated Overlapping roots are allowed in 2.1
	 */
	public static boolean isOverlappingRoots(IPath rootPath1, IPath rootPath2) {
		if (rootPath1 == null || rootPath2 == null) {
			return false;
		}
		return rootPath1.isPrefixOf(rootPath2) || rootPath2.isPrefixOf(rootPath1);
	}

	/*
	 * Returns the current identifier extracted by the scanner (without unicode
	 * escapes) from the given id and for the given source and compliance levels.
	 * Returns <code>null</code> if the id was not valid
	 */
	private static synchronized char[] scannedIdentifier(String id, String sourceLevel, String complianceLevel) {
		if (id == null) {
			return null;
		}
		// Set scanner for given source and compliance levels
		SCANNER.sourceLevel = sourceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(sourceLevel);
		SCANNER.complianceLevel = complianceLevel == null ? ClassFileConstants.JDK1_3 : CompilerOptions.versionToJdkLevel(complianceLevel);

		try {
			SCANNER.setSource(id.toCharArray());
			int token = SCANNER.scanIdentifier();
			if (token != TerminalTokens.TokenNameIdentifier) return null;
			if (SCANNER.currentPosition == SCANNER.eofPosition) { // to handle case where we had an ArrayIndexOutOfBoundsException
				try {
					return SCANNER.getCurrentIdentifierSource();
				} catch (ArrayIndexOutOfBoundsException e) {
					return null;
				}
			} else {
				return null;
			}
		}
		catch (InvalidInputException e) {
			return null;
		}
	}

	/**
	 * Validate the given compilation unit name.
	 * <p>
	 * A compilation unit name must obey the following rules:
	 * <ul>
	 * <li> it must not be null
	 * <li> it must be suffixed by a dot ('.') followed by one of the
	 *       {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
	 * <li> its prefix must be a valid identifier
	 * <li> it must not contain any characters or substrings that are not valid
	 *		   on the file system on which workspace root is located.
	 * </ul>
	 * </p>
	 * @param name the name of a compilation unit
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a compilation unit name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @deprecated Use {@link #validateCompilationUnitName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateCompilationUnitName(String name) {
		return validateCompilationUnitName(name,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * Validate the given compilation unit name for the given source and compliance levels.
	 * <p>
	 * A compilation unit name must obey the following rules:
	 * <ul>
	 * <li> it must not be null
	 * <li> it must be suffixed by a dot ('.') followed by one of the
	 *       {@link JavaCore#getJavaLikeExtensions() Java-like extensions}
	 * <li> its prefix must be a valid identifier
	 * <li> it must not contain any characters or substrings that are not valid
	 *		   on the file system on which workspace root is located.
	 * </ul>
	 * </p>
	 * @param name the name of a compilation unit
	 * @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 compilation unit name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.3
	 */
	public static IStatus validateCompilationUnitName(String name, String sourceLevel, String complianceLevel) {
		if (name == null) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_unit_nullName, null);
		}
		if (!org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name)) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_unit_notJavaName, null);
		}
		String identifier;
		int index;
		index = name.lastIndexOf('.');
		if (index == -1) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_unit_notJavaName, null);
		}
		identifier = name.substring(0, index);
		// JSR-175 metadata strongly recommends "package-info.java" as the
		// file in which to store package annotations and
		// the package-level spec (replaces package.html)
		if (!CharOperation.equals(identifier.toCharArray(), TypeConstants.PACKAGE_INFO_NAME)
				&& !CharOperation.equals(identifier.toCharArray(), TypeConstants.MODULE_INFO_NAME)) {
			IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
			if (!status.isOK()) {
				return status;
			}
		}
		IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
		if (!status.isOK()) {
			return status;
		}
		return JavaModelStatus.VERIFIED_OK;
	}

	/**
	 * Validate the given .class file name.
	 * <p>
	 * A .class file name must obey the following rules:
	 * <ul>
	 * <li> it must not be null
	 * <li> it must include the <code>".class"</code> suffix
	 * <li> its prefix must be a valid identifier
	 * <li> it must not contain any characters or substrings that are not valid
	 *		   on the file system on which workspace root is located.
	 * </ul>
	 * </p>
	 * @param name the name of a .class file
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a .class file name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 2.0
	 * @deprecated Use {@link #validateClassFileName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateClassFileName(String name) {
		return validateClassFileName(name, CompilerOptions.VERSION_1_3, CompilerOptions.VERSION_1_3);
	}

	/**
	 * Validate the given .class file name for the given source and compliance levels.
	 * <p>
	 * A .class file name must obey the following rules:
	 * <ul>
	 * <li> it must not be null
	 * <li> it must include the <code>".class"</code> suffix
	 * <li> its prefix must be a valid identifier
	 * <li> it must not contain any characters or substrings that are not valid
	 *		   on the file system on which workspace root is located.
	 * </ul>
	 * </p>
	 * @param name the name of a .class file
	 * @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 .class file name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.3
	 */
	public static IStatus validateClassFileName(String name, String sourceLevel, String complianceLevel) {
		if (name == null) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_classFile_nullName, null);		}
		if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_classFile_notClassFileName, null);
		}
		String identifier;
		int index;
		index = name.lastIndexOf('.');
		if (index == -1) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_classFile_notClassFileName, null);
		}
		identifier = name.substring(0, index);
		// JSR-175 metadata strongly recommends "package-info.java" as the
		// file in which to store package annotations and
		// the package-level spec (replaces package.html)
		if (!CharOperation.equals(identifier.toCharArray(), TypeConstants.PACKAGE_INFO_NAME)
				&& !CharOperation.equals(identifier.toCharArray(), TypeConstants.MODULE_INFO_NAME)) {
			IStatus status = validateIdentifier(identifier, sourceLevel, complianceLevel);
			if (!status.isOK()) {
				return status;
			}
		}
		IStatus status = ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
		if (!status.isOK()) {
			return status;
		}
		return JavaModelStatus.VERIFIED_OK;
	}

	/**
	 * Validate the given field name.
	 * <p>
	 * Syntax of a field name corresponds to VariableDeclaratorId (JLS2 8.3).
	 * For example, <code>"x"</code>.
	 *
	 * @param name the name of a field
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a field name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @deprecated Use {@link #validateFieldName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateFieldName(String name) {
		return validateIdentifier(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * Validate the given field name for the given source and compliance levels.
	 * <p>
	 * Syntax of a field name corresponds to VariableDeclaratorId (JLS2 8.3).
	 * For example, <code>"x"</code>.
	 *
	 * @param name the name of a field
	 * @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 field name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.3
	 */
	public static IStatus validateFieldName(String name, String sourceLevel, String complianceLevel) {
		return validateIdentifier(name, sourceLevel, complianceLevel);
	}

	/**
	 * Validate the given Java identifier.
	 * 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
	 * @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
	 * @deprecated Use {@link #validateIdentifier(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateIdentifier(String id) {
		return validateIdentifier(id,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * 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 import declaration name.
	 * <p>
	 * The name of an import corresponds to a fully qualified type name
	 * or an on-demand package name as defined by ImportDeclaration (JLS2 7.5).
	 * For example, <code>"java.util.*"</code> or <code>"java.util.Hashtable"</code>.
	 *
	 * @param name the import declaration
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as an import declaration, otherwise a status
	 *		object indicating what is wrong with the name
	 * @deprecated Use {@link #validateImportDeclaration(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateImportDeclaration(String name) {
		return validateImportDeclaration(name,CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * Validate the given import declaration name for the given source and compliance levels.
	 * <p>
	 * The name of an import corresponds to a fully qualified type name
	 * or an on-demand package name as defined by ImportDeclaration (JLS2 7.5).
	 * For example, <code>"java.util.*"</code> or <code>"java.util.Hashtable"</code>.
	 *
	 * @param name the import declaration
	 * @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 an import declaration, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.3
	 */
	public static IStatus validateImportDeclaration(String name, String sourceLevel, String complianceLevel) {
		if (name == null || name.length() == 0) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_import_nullImport, null);
		}
		if (name.charAt(name.length() - 1) == '*') {
			if (name.charAt(name.length() - 2) == '.') {
				return validatePackageName(name.substring(0, name.length() - 2), sourceLevel, complianceLevel);
			} else {
				return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_import_unqualifiedImport, null);
			}
		}
		return validatePackageName(name, sourceLevel, complianceLevel);
	}

	/**
	 * Validate the given Java type name, either simple or qualified.
	 * For example, <code>"java.lang.Object"</code>, or <code>"Object"</code>.
	 * <p>
	 *
	 * @param name the name of a type
	 * @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
	 * @deprecated Use {@link #validateJavaTypeName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateJavaTypeName(String name) {
		return validateJavaTypeName(name, JavaCore.VERSION_1_3, JavaCore.VERSION_1_3);
	}

	/**
	 * 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>
	 * 
	 * <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'.
	 * </p>
	 *
	 * @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
	 * @see JavaCore#VERSION_9
	 */
	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 method name.
	 * The special names "&lt;init&gt;" and "&lt;clinit&gt;" are not valid.
	 * <p>
	 * The syntax for a method  name is defined by Identifier
	 * of MethodDeclarator (JLS2 8.4). For example "println".
	 *
	 * @param name the name of a method
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a method name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @deprecated Use {@link #validateMethodName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateMethodName(String name) {
		return validateMethodName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * Validate the given method name for the given source and compliance levels.
	 * The special names "&lt;init&gt;" and "&lt;clinit&gt;" are not valid.
	 * <p>
	 * The syntax for a method  name is defined by Identifier
	 * of MethodDeclarator (JLS2 8.4). For example "println".
	 *
	 * @param name the name of a method
	 * @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 method name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.3
	 */
	public static IStatus validateMethodName(String name, String sourceLevel, String complianceLevel) {
		return validateIdentifier(name, sourceLevel,complianceLevel);
	}

	/**
	 * Validate the given package name.
	 * <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
	 * @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
	 * @deprecated Use {@link #validatePackageName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validatePackageName(String name) {
		return validatePackageName(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * 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);
		}
		if (DOT_DOT.matcher(name).find()) {
			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;
	}

	/**
	 * Validate the given module name for the given source and compliance levels.
	 * <p>
	 * The syntax of a module name corresponds to ModuleName as
	 * defined by ModuleDeclaration (JLS 7.6). For example, <code>"java.base"</code>.
	 * <p>
	 * Note that the given name must not be empty. Also each segment of the module
	 * name (separated by ".") must be a valid Java identifier as per JLS 3.8.
	 *
	 * @param name name of a module
	 * @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 module name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.14
	 */
	public static IStatus validateModuleName(String name, String sourceLevel, String complianceLevel) {

		if (name == null) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_nullName, null);
		}
		int length;
		if ((length = name.length()) == 0) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_emptyName, null);
		}

		if (name.charAt(0) == DOT || name.charAt(length-1) == DOT) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_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_module_nameWithBlanks, null);
		}
		if (DOT_DOT.matcher(name).find()) {
			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.convention_module_consecutiveDotsName, null);
		}
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		StringTokenizer st = new StringTokenizer(name, "."); //$NON-NLS-1$
		boolean firstToken = true;
		IStatus warningStatus = null;
		while (st.hasMoreTokens()) {
			String segment = st.nextToken();
			segment = segment.trim(); // grammar allows spaces
			char[] scannedID = scannedIdentifier(segment, sourceLevel, complianceLevel);
			if (scannedID == null) {
				return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_illegalIdentifier, segment), null);
			}
			if (firstToken && PREFIX_JAVA.matcher(segment).find()) {
				warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.bind(Messages.convention_module_javaName), null);
			}
			if (TERMINAL_DIGIT.matcher(segment).find()) {
				warningStatus = new Status(IStatus.WARNING, JavaCore.PLUGIN_ID, -1, Messages.convention_module_terminalDigits, 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_module_uppercaseName, null);
				}
			}
			firstToken = false;
		}
		if (warningStatus != null) {
			return warningStatus;
		}
		return JavaModelStatus.VERIFIED_OK;
	}

	/**
	 * Validate a given classpath and output location for a project, using the following rules:
	 * <ul>
	 *   <li> Classpath entries cannot collide with each other; that is, all entry paths must be unique.
	 *   <li> The project output location path cannot be null, must be absolute and located inside the project.
	 *   <li> Specific output locations (specified on source entries) can be null, if not they must be located inside the project,
	 *   <li> A project entry cannot refer to itself directly (that is, a project cannot prerequisite itself).
     *   <li> Classpath entries or output locations cannot coincide or be nested in each other, except for the following scenarios listed below:
	 *      <ul><li> A source folder can coincide with its own output location, in which case this output can then contain library archives.
	 *                     However, a specific output location cannot coincide with any library or a distinct source folder than the one referring to it.<br>
	 *                     Note: Since 3.8, this behavior can be overridden by configuring {@link JavaCore#CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE}
	 *                     </li>
	 *              <li> A source/library folder can be nested in any source folder as long as the nested folder is excluded from the enclosing one. </li>
	 * 			<li> An output location can be nested in a source folder, if the source folder coincides with the project itself, or if the output
	 * 					location is excluded from the source folder.
	 *      </ul>
	 * </ul>
	 *
	 *  Note that the classpath entries are not validated automatically. Only bound variables or containers are considered
	 *  in the checking process (this allows to perform a consistency check on a classpath which has references to
	 *  yet non existing projects, folders, ...).
	 *  <p>
	 *  This validation is intended to anticipate classpath issues prior to assigning it to a project. In particular, it will automatically
	 *  be performed during the classpath setting operation (if validation fails, the classpath setting will not complete).
	 *  <p>
	 * @param javaProject the given java project
	 * @param rawClasspath the given classpath
	 * @param projectOutputLocation the given output location
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given classpath and output location are compatible, otherwise a status
	 *		object indicating what is wrong with the classpath or output location
	 * @since 2.0
	 */
	public static IJavaModelStatus validateClasspath(IJavaProject javaProject, IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {

		return ClasspathEntry.validateClasspath(javaProject, rawClasspath, projectOutputLocation);
	}

	/**
	 * Returns a Java model status describing the problem related to this classpath entry if any,
	 * a status object with code <code>IStatus.OK</code> if the entry is fine (that is, if the
	 * given classpath entry denotes a valid element to be referenced onto a classpath).
	 *
	 * @param project the given java project
	 * @param entry the given classpath entry
	 * @param checkSourceAttachment a flag to determine if source attachment should be checked
	 * @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
	 * @since 2.0
	 */
	public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment){
		return ClasspathEntry.validateClasspathEntry(project, entry, checkSourceAttachment, false/*not referred by container*/);
	}

	/**
	 * Validate the given type variable name.
	 * <p>
	 * Syntax of a type variable name corresponds to a Java identifier (JLS3 4.3).
	 * For example, <code>"E"</code>.
	 *
	 * @param name the name of a type variable
	 * @return a status object with code <code>IStatus.OK</code> if
	 *		the given name is valid as a type variable name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.1
	 * @deprecated Use {@link #validateTypeVariableName(String id, String sourceLevel, String complianceLevel)} instead
	 */
	public static IStatus validateTypeVariableName(String name) {
		return validateIdentifier(name, CompilerOptions.VERSION_1_3,CompilerOptions.VERSION_1_3);
	}

	/**
	 * Validate the given type variable name for the given source and compliance levels.
	 * <p>
	 * Syntax of a type variable name corresponds to a Java identifier (JLS3 4.3).
	 * For example, <code>"E"</code>.
	 *
	 * @param name the name of a type variable
	 * @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 type variable name, otherwise a status
	 *		object indicating what is wrong with the name
	 * @since 3.3
	 */
	public static IStatus validateTypeVariableName(String name, String sourceLevel, String complianceLevel) {
		return validateIdentifier(name, sourceLevel, complianceLevel);
	}

	/**
	 * Validate that all compiler options of the given project match keys and values
	 * described in {@link JavaCore#getDefaultOptions()} method.
	 *
	 * @param javaProject the given java project
	 * @param inheritJavaCoreOptions inherit project options from JavaCore or not.
	 * @return a status object with code <code>IStatus.OK</code> if all project
	 *		compiler options are valid, otherwise a status object indicating what is wrong
	 *		with the keys and their value.
	 * @since 3.1
	 * TODO (frederic) finalize for all possible options (JavaCore, DefaultCodeFormatterOptions, AssistOptions) and open to API
	 */
	/*
	public static IStatus validateCompilerOptions(IJavaProject javaProject, boolean inheritJavaCoreOptions)	  {
		return validateCompilerOptions(javaProject.getOptions(inheritJavaCoreOptions));
	}
	*/

	/**
	 * Validate that all compiler options of the given project match keys and values
	 * described in {@link JavaCore#getDefaultOptions()} method.
	 *
	 * @param compilerOptions Map of options
	 * @return a status object with code <code>IStatus.OK</code> if all
	 *		compiler options are valid, otherwise a status object indicating what is wrong
	 *		with the keys and their value.
	 * @since 3.1
	 */
	/*
	public static IStatus validateCompilerOptions(Map compilerOptions)	  {

		// Get current options
		String compliance = (String) compilerOptions.get(JavaCore.COMPILER_COMPLIANCE);
		String source = (String) compilerOptions.get(JavaCore.COMPILER_SOURCE);
		String target = (String) compilerOptions.get(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM);
		if (compliance == null && source == null && target == null) {
			return JavaModelStatus.VERIFIED_OK; // default is OK
		}

		// Initialize multi-status
		List errors = new ArrayList();

		// Set default for compliance if necessary (not set on project and not inherited...)
		if (compliance == null) {
			compliance = JavaCore.getOption(JavaCore.COMPILER_COMPLIANCE);
		}

		// Verify compliance level value and set source and target default if necessary
		long complianceLevel = 0;
		long sourceLevel = 0;
		long targetLevel = 0;
		if (JavaCore.VERSION_1_3.equals(compliance)) {
			complianceLevel = ClassFileConstants.JDK1_3;
			if (source == null) {
				source = JavaCore.VERSION_1_3;
				sourceLevel = ClassFileConstants.JDK1_3;
			}
			if (target == null) {
				target = JavaCore.VERSION_1_1;
				targetLevel = ClassFileConstants.JDK1_1;
			}
		} else if (JavaCore.VERSION_1_4.equals(compliance)) {
			complianceLevel = ClassFileConstants.JDK1_4;
			if (source == null) {
				source = JavaCore.VERSION_1_3;
				sourceLevel = ClassFileConstants.JDK1_3;
			}
			if (target == null) {
				target = JavaCore.VERSION_1_2;
				targetLevel = ClassFileConstants.JDK1_2;
			}
		} else if (JavaCore.VERSION_1_5.equals(compliance)) {
			complianceLevel = ClassFileConstants.JDK1_5;
			if (source == null) {
				source = JavaCore.VERSION_1_5;
				sourceLevel = ClassFileConstants.JDK1_5;
			}
			if (target == null) {
				target = JavaCore.VERSION_1_5;
				targetLevel = ClassFileConstants.JDK1_5;
			}
		} else {
			// compliance is not valid
			errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", compliance==null?"":compliance, JavaCore.COMPILER_COMPLIANCE))); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// Verify source value and set default for target if necessary
		 if (JavaCore.VERSION_1_4.equals(source)) {
			sourceLevel = ClassFileConstants.JDK1_4;
			if (target == null) {
				target = JavaCore.VERSION_1_4;
				targetLevel = ClassFileConstants.JDK1_4;
			}
		} else if (JavaCore.VERSION_1_5.equals(source)) {
			sourceLevel = ClassFileConstants.JDK1_5;
			if (target == null) {
				target = JavaCore.VERSION_1_5;
				targetLevel = ClassFileConstants.JDK1_5;
			}
		} else if (JavaCore.VERSION_1_3.equals(source)) {
			sourceLevel = ClassFileConstants.JDK1_3;
		} else {
			// source is not valid
			errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", source==null?"":source, JavaCore.COMPILER_SOURCE))); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// Verify target value
		 if (targetLevel == 0) {
			 targetLevel = CompilerOptions.versionToJdkLevel(target);
			 if (targetLevel == 0) {
				// target is not valid
				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.invalidCompilerOption", target==null?"":target, JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM))); //$NON-NLS-1$ //$NON-NLS-2$
			 }
		}

		// Check and set compliance/source/target compatibilities (only if they have valid values)
		if (complianceLevel != 0 && sourceLevel != 0 && targetLevel != 0) {
			// target must be 1.5 if source is 1.5
			if (sourceLevel >= ClassFileConstants.JDK1_5 && targetLevel < ClassFileConstants.JDK1_5) {
				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleTargetForSource", target, JavaCore.VERSION_1_5))); //$NON-NLS-1$
			}
	   		else
		   		// target must be 1.4 if source is 1.4
	   			if (sourceLevel >= ClassFileConstants.JDK1_4 && targetLevel < ClassFileConstants.JDK1_4) {
					errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleTargetForSource", target, JavaCore.VERSION_1_4))); //$NON-NLS-1$
	   		}
			// target cannot be greater than compliance level
			if (complianceLevel < targetLevel){
				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForTarget", compliance, JavaCore.VERSION_1_4))); //$NON-NLS-1$
			}
			// compliance must be 1.5 if source is 1.5
			if (source.equals(JavaCore.VERSION_1_5) && complianceLevel < ClassFileConstants.JDK1_5) {
				errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForSource", compliance, JavaCore.VERSION_1_5))); //$NON-NLS-1$
			} else
				// compliance must be 1.4 if source is 1.4
				if (source.equals(JavaCore.VERSION_1_4) && complianceLevel < ClassFileConstants.JDK1_4) {
					errors.add(new JavaModelStatus(IStatus.ERROR, Util.bind("convention.compiler.incompatibleComplianceForSource", compliance, JavaCore.VERSION_1_4))); //$NON-NLS-1$
			}
		}

		// Return status
		int size = errors.size();
		switch (size) {
			case 0:
				return JavaModelStatus.VERIFIED_OK;
			case 1:
				return (IStatus) errors.get(0);
			default:
				IJavaModelStatus[] allStatus = new IJavaModelStatus[size];
				errors.toArray(allStatus);
				return JavaModelStatus.newMultiStatus(allStatus);
		}
	}
	*/
}
