/*******************************************************************************
 * Copyright (c) 2000, 2018 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
 *     John Glassmyer <jogl@google.com> - import group sorting is broken - https://bugs.eclipse.org/430303
 *     Lars Vogel <Lars.Vogel@vogella.com> - Contributions for
 *     						Bug 473178
 *******************************************************************************/

package org.aspectj.org.eclipse.jdt.core.dom.rewrite;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.aspectj.org.eclipse.jdt.core.Flags;
import org.aspectj.org.eclipse.jdt.core.ICompilationUnit;
import org.aspectj.org.eclipse.jdt.core.IImportDeclaration;
import org.aspectj.org.eclipse.jdt.core.IType;
import org.aspectj.org.eclipse.jdt.core.ITypeRoot;
import org.aspectj.org.eclipse.jdt.core.JavaCore;
import org.aspectj.org.eclipse.jdt.core.JavaModelException;
import org.aspectj.org.eclipse.jdt.core.Signature;
import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
import org.aspectj.org.eclipse.jdt.core.dom.AST;
import org.aspectj.org.eclipse.jdt.core.dom.ASTParser;
import org.aspectj.org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.aspectj.org.eclipse.jdt.core.dom.AnnotatableType;
import org.aspectj.org.eclipse.jdt.core.dom.Annotation;
import org.aspectj.org.eclipse.jdt.core.dom.ArrayInitializer;
import org.aspectj.org.eclipse.jdt.core.dom.ArrayType;
import org.aspectj.org.eclipse.jdt.core.dom.CharacterLiteral;
import org.aspectj.org.eclipse.jdt.core.dom.CompilationUnit;
import org.aspectj.org.eclipse.jdt.core.dom.Dimension;
import org.aspectj.org.eclipse.jdt.core.dom.Expression;
import org.aspectj.org.eclipse.jdt.core.dom.FieldAccess;
import org.aspectj.org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.aspectj.org.eclipse.jdt.core.dom.IBinding;
import org.aspectj.org.eclipse.jdt.core.dom.IMemberValuePairBinding;
import org.aspectj.org.eclipse.jdt.core.dom.IMethodBinding;
import org.aspectj.org.eclipse.jdt.core.dom.ITypeBinding;
import org.aspectj.org.eclipse.jdt.core.dom.IVariableBinding;
import org.aspectj.org.eclipse.jdt.core.dom.ImportDeclaration;
import org.aspectj.org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.aspectj.org.eclipse.jdt.core.dom.MemberValuePair;
import org.aspectj.org.eclipse.jdt.core.dom.Modifier;
import org.aspectj.org.eclipse.jdt.core.dom.Name;
import org.aspectj.org.eclipse.jdt.core.dom.NormalAnnotation;
import org.aspectj.org.eclipse.jdt.core.dom.ParameterizedType;
import org.aspectj.org.eclipse.jdt.core.dom.PrimitiveType;
import org.aspectj.org.eclipse.jdt.core.dom.SimpleName;
import org.aspectj.org.eclipse.jdt.core.dom.SimpleType;
import org.aspectj.org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.aspectj.org.eclipse.jdt.core.dom.StringLiteral;
import org.aspectj.org.eclipse.jdt.core.dom.Type;
import org.aspectj.org.eclipse.jdt.core.dom.TypeLiteral;
import org.aspectj.org.eclipse.jdt.core.dom.WildcardType;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportRewriteAnalyzer;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportRewriteConfiguration;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportRewriteConfiguration.ImplicitImportIdentification;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.imports.ImportRewriteConfiguration.ImportContainerSorting;
import org.aspectj.org.eclipse.jdt.internal.core.util.Messages;
import org.aspectj.org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;


/**
 * The {@link ImportRewrite} helps updating imports following a import order and on-demand imports threshold as configured by a project.
 * <p>
 * The import rewrite is created on a compilation unit and collects references to types that are added or removed. When adding imports, e.g. using
 * {@link #addImport(String)}, the import rewrite evaluates if the type can be imported and returns the a reference to the type that can be used in code.
 * This reference is either unqualified if the import could be added, or fully qualified if the import failed due to a conflict with another element of the same name.
 * </p>
 * <p>
 * On {@link #rewriteImports(IProgressMonitor)} the rewrite translates these descriptions into
 * text edits that can then be applied to the original source. The rewrite infrastructure tries to generate minimal text changes and only
 * works on the import statements. It is possible to combine the result of an import rewrite with the result of a {@link org.aspectj.org.eclipse.jdt.core.dom.rewrite.ASTRewrite}
 * as long as no import statements are modified by the AST rewrite.
 * </p>
 * <p>The options controlling the import order and on-demand thresholds are:
 * <ul><li>{@link #setImportOrder(String[])} specifies the import groups and their preferred order</li>
 * <li>{@link #setOnDemandImportThreshold(int)} specifies the number of imports in a group needed for a on-demand import statement (star import)</li>
 * <li>{@link #setStaticOnDemandImportThreshold(int)} specifies the number of static imports in a group needed for a on-demand import statement (star import)</li>
 *</ul>
 * This class is not intended to be subclassed.
 * </p>
 * @since 3.2
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public final class ImportRewrite {
	/**
	 * Used to determine how a type will be used, so that unwanted annotations can be filtered,
	 * which is in particular relevant for avoiding redundant null annotations in the scope of {@code @NonNullByDefault}. 
	 * This enum is a superset of org.aspectj.org.eclipse.jdt.annotation.DefaultLocation, and roughly corresponds
	 * to the classification of type locations as introduced by JSR 308.
	 *
	 * @since 3.13
	 */
	public enum TypeLocation {
		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.PARAMETER
		 * 
		 * @since 3.13
		 */
		PARAMETER,

		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.RETURN_TYPE
		 * 
		 * @since 3.13
		 */
		RETURN_TYPE,

		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.FIELD
		 * 
		 * @since 3.13
		 */
		FIELD,

		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.TYPE_PARAMETER
		 * 
		 * @since 3.13
		 */
		TYPE_PARAMETER,

		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.TYPE_BOUND
		 * 
		 * @since 3.13
		 */
		TYPE_BOUND,

		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.TYPE_ARGUMENT
		 * 
		 * @since 3.13
		 */
		TYPE_ARGUMENT,

		/**
		 * see org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.ARRAY_CONTENTS
		 * 
		 * @since 3.13
		 */
		ARRAY_CONTENTS,

		/**
		 * The special value {@link #LOCAL_VARIABLE} is used for local variables: their nullness is determines by flow analysis,
		 * so top level nullness annotations are usually not needed for local variables (unless their type is a free
		 * type variable). Does not correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		LOCAL_VARIABLE,

		/**
		 * The special value {@link #CAST} is used for casts.
		 * Casts are never affected by {@code @NonNullByDefault}
		 * Does not correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		CAST,
		
		/**
		 * The special value {@link #INSTANCEOF} is used for {@code instanceof} expressions.
		 * Null annotations are not supported in this location.
		 * Does not correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		INSTANCEOF,

		/**
		 * The special value {@link #NEW} is used for {@code new} expressions (object allocations). 
		 * Null annotations are not supported in this location.
		 * Does not correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		NEW,

		/**
		 * The special value {@link #RECEIVER} is used for the receiver type in a method declaration or method reference.
		 * Null annotations are not supported in this location.
		 * Does not correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		RECEIVER,

		/**
		 * The special value {@link #EXCEPTION} is used for exception types in catch and throws declarations, which are
		 * implicitly non-null. Does not correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		EXCEPTION,

		/**
		 * The special value {@link #OTHER} is used for locations where type annotations are illegal, like type literals
		 * (X.class), annotations, or as scope for static field accesses. Does not correspond to a value in
		 * org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		OTHER,

		/**
		 * The special value {@link #UNKNOWN} is used for invocations that don't specify the intended type usage. Does not
		 * correspond to a value in org.aspectj.org.eclipse.jdt.annotation.DefaultLocation.
		 * 
		 * @since 3.13
		 */
		UNKNOWN,
	}

	/**
	 * A {@link ImportRewrite.ImportRewriteContext} can optionally be used in e.g. {@link ImportRewrite#addImport(String, ImportRewrite.ImportRewriteContext)} to
	 * give more information about the types visible in the scope. These types can be for example inherited inner types where it is
	 * unnecessary to add import statements for.
	 *
	 * </p>
	 * <p>
	 * This class can be implemented by clients.
	 * </p>
	 */
	public static abstract class ImportRewriteContext {

		/**
		 * Result constant signaling that the given element is know in the context.
		 */
		public final static int RES_NAME_FOUND= 1;

		/**
		 * Result constant signaling that the given element is not know in the context.
		 */
		public final static int RES_NAME_UNKNOWN= 2;

		/**
		 * Result constant signaling that the given element is conflicting with an other element in the context.
		 */
		public final static int RES_NAME_CONFLICT= 3;

		/**
		 * Result constant signaling that the given element must be imported explicitly (and must not be folded into
		 * an on-demand import or filtered as an implicit import).
		 *
		 * @since 3.11
		 */
		public final static int RES_NAME_UNKNOWN_NEEDS_EXPLICIT_IMPORT= 4;

		/**
		 * Kind constant specifying that the element is a type import.
		 */
		public final static int KIND_TYPE= 1;

		/**
		 * Kind constant specifying that the element is a static field import.
		 */
		public final static int KIND_STATIC_FIELD= 2;

		/**
		 * Kind constant specifying that the element is a static method import.
		 */
		public final static int KIND_STATIC_METHOD= 3;

		/**
		 * Searches for the given element in the context and reports if the element is known ({@link #RES_NAME_FOUND}),
		 * unknown ({@link #RES_NAME_UNKNOWN}), unknown in the context but known to require an explicit import
		 * ({@link #RES_NAME_UNKNOWN_NEEDS_EXPLICIT_IMPORT}), or if its name conflicts ({@link #RES_NAME_CONFLICT})
		 * with an other element.
		 *
		 * @param qualifier The qualifier of the element, can be package or the qualified name of a type
		 * @param name The simple name of the element; either a type, method or field name or * for on-demand imports.
		 * @param kind The kind of the element. Can be either {@link #KIND_TYPE}, {@link #KIND_STATIC_FIELD} or
		 * {@link #KIND_STATIC_METHOD}. Implementors should be prepared for new, currently unspecified kinds and return
		 * {@link #RES_NAME_UNKNOWN} by default.
		 * @return Returns the result of the lookup. Can be either {@link #RES_NAME_FOUND}, {@link #RES_NAME_UNKNOWN},
		 * {@link #RES_NAME_CONFLICT}, or {@link #RES_NAME_UNKNOWN_NEEDS_EXPLICIT_IMPORT}.
		 */
		public abstract int findInContext(String qualifier, String name, int kind);

		/**
		 * This method can be overridden in subclasses to remove annotations that are redundant, e.g. because of NonNullByDefault.
		 * @param annotations The array of type annotations to be filtered.
		 * @param location Specifies how the type being annotated will be used.
		 * @param type the type being annotated
		 * @return Returns the annotations that should be added to the type.
		 * @since 3.13
		 */
		public IAnnotationBinding[] removeRedundantTypeAnnotations(IAnnotationBinding[] annotations, TypeLocation location, ITypeBinding type) {
			return annotations;
		}
	}

	private static final char STATIC_PREFIX= 's';
	private static final char NORMAL_PREFIX= 'n';

	/** @deprecated using deprecated code */
	private static final int JLS8_INTERNAL = AST.JLS8;

	private final ImportRewriteContext defaultContext;

	private final ICompilationUnit compilationUnit;
	private final CompilationUnit astRoot;

	private final boolean restoreExistingImports;
	private final List existingImports;
	private final Map importsKindMap;

	private String[] importOrder;
	private int importOnDemandThreshold;
	private int staticImportOnDemandThreshold;

	private List<String> addedImports;
	private List<String> removedImports;

	/**
	 * Simple names of non-static imports which must not be reduced into on-demand imports
	 * or filtered out as implicit.
	 */
	private Set<String> typeExplicitSimpleNames;

	/**
	 * Simple names of static imports which must not be reduced into on-demand imports
	 * or filtered out as implicit.
	 */
	private Set<String> staticExplicitSimpleNames;

	private String[] createdImports;
	private String[] createdStaticImports;

	private boolean filterImplicitImports;
	private boolean useContextToFilterImplicitImports;

	/**
	 * Creates an {@link ImportRewrite} from an {@link ICompilationUnit}. If <code>restoreExistingImports</code>
	 * is <code>true</code>, all existing imports are kept, and new imports will be inserted at best matching locations. If
	 * <code>restoreExistingImports</code> is <code>false</code>, the existing imports will be removed and only the
	 * newly added imports will be created.
	 * <p>
	 * Note that {@link #create(CompilationUnit, boolean)} is more efficient than this method if an AST for
	 * the compilation unit is already available.
	 * </p>
	 * @param cu the compilation unit to create the imports for
	 * @param restoreExistingImports specifies if the existing imports should be kept or removed.
	 * @return the created import rewriter.
	 * @throws JavaModelException thrown when the compilation unit could not be accessed.
	 */
	public static ImportRewrite create(ICompilationUnit cu, boolean restoreExistingImports) throws JavaModelException {
		if (cu == null) {
			throw new IllegalArgumentException("Compilation unit must not be null"); //$NON-NLS-1$
		}
		List existingImport= null;
		if (restoreExistingImports) {
			existingImport= new ArrayList();
			IImportDeclaration[] imports= cu.getImports();
			for (int i= 0; i < imports.length; i++) {
				IImportDeclaration curr= imports[i];
				char prefix= Flags.isStatic(curr.getFlags()) ? STATIC_PREFIX : NORMAL_PREFIX;
				existingImport.add(prefix + curr.getElementName());
			}
		}
		return new ImportRewrite(cu, null, existingImport);
	}

	/**
	 * Creates an {@link ImportRewrite} from an AST ({@link CompilationUnit}). The AST has to be created from an
	 * {@link ICompilationUnit}, that means {@link ASTParser#setSource(ICompilationUnit)} has been used when creating the
	 * AST. If <code>restoreExistingImports</code> is <code>true</code>, all existing imports are kept, and new imports
	 * will be inserted at best matching locations. If <code>restoreExistingImports</code> is <code>false</code>, the
	 * existing imports will be removed and only the newly added imports will be created.
	 * <p>
	 * Note that this method is more efficient than using {@link #create(ICompilationUnit, boolean)} if an AST is already available.
	 * </p>
	 * @param astRoot the AST root node to create the imports for
	 * @param restoreExistingImports specifies if the existing imports should be kept or removed.
	 * @return the created import rewriter.
	 * @throws IllegalArgumentException thrown when the passed AST is null or was not created from a compilation unit.
	 */
	public static ImportRewrite create(CompilationUnit astRoot, boolean restoreExistingImports) {
		if (astRoot == null) {
			throw new IllegalArgumentException("AST must not be null"); //$NON-NLS-1$
		}
		ITypeRoot typeRoot = astRoot.getTypeRoot();
		if (!(typeRoot instanceof ICompilationUnit)) {
			throw new IllegalArgumentException("AST must have been constructed from a Java element"); //$NON-NLS-1$
		}
		List existingImport= null;
		if (restoreExistingImports) {
			existingImport= new ArrayList();
			List imports= astRoot.imports();
			for (int i= 0; i < imports.size(); i++) {
				ImportDeclaration curr= (ImportDeclaration) imports.get(i);
				StringBuffer buf= new StringBuffer();
				buf.append(curr.isStatic() ? STATIC_PREFIX : NORMAL_PREFIX).append(curr.getName().getFullyQualifiedName());
				if (curr.isOnDemand()) {
					if (buf.length() > 1)
						buf.append('.');
					buf.append('*');
				}
				existingImport.add(buf.toString());
			}
		}
		return new ImportRewrite((ICompilationUnit) typeRoot, astRoot, existingImport);
	}

	private ImportRewrite(ICompilationUnit cu, CompilationUnit astRoot, List existingImports) {
		this.compilationUnit= cu;
		this.astRoot= astRoot; // might be null
		if (existingImports != null) {
			this.existingImports= existingImports;
			this.restoreExistingImports= !existingImports.isEmpty();
		} else {
			this.existingImports= new ArrayList();
			this.restoreExistingImports= false;
		}
		this.filterImplicitImports= true;
		// consider that no contexts are used
		this.useContextToFilterImplicitImports = false;

		this.defaultContext= new ImportRewriteContext() {
			@Override
			public int findInContext(String qualifier, String name, int kind) {
				return findInImports(qualifier, name, kind);
			}
		};
		this.addedImports= new ArrayList<>();
		this.removedImports= new ArrayList<>();
		this.typeExplicitSimpleNames = new HashSet<>();
		this.staticExplicitSimpleNames = new HashSet<>();
		this.createdImports= null;
		this.createdStaticImports= null;

		this.importOrder= CharOperation.NO_STRINGS;
		this.importOnDemandThreshold= 99;
		this.staticImportOnDemandThreshold= 99;
		
		this.importsKindMap = new HashMap();
	}


	 /**
	 * Defines the import groups and order to be used by the {@link ImportRewrite}.
	 * Imports are added to the group matching their qualified name most. The empty group name groups all imports not matching
	 * any other group. Static imports are managed in separate groups. Static import group names are prefixed with a '#' character.
	 * @param order A list of strings defining the import groups. A group name must be a valid package name or empty. If can be
	 * prefixed by the '#' character for static import groups
	 */
	public void setImportOrder(String[] order) {
		if (order == null)
			throw new IllegalArgumentException("Order must not be null"); //$NON-NLS-1$
		this.importOrder= order;
	}

	 /**
	 *	Sets the on-demand import threshold for normal (non-static) imports.
	 *	This threshold defines the number of imports that need to be in a group to use
	 * a on-demand (star) import declaration instead.
	 *
	 * @param threshold a positive number defining the on-demand import threshold
	 * for normal (non-static) imports.
	 * @throws IllegalArgumentException a {@link IllegalArgumentException} is thrown
	 * if the number is not positive.
     */
	public void setOnDemandImportThreshold(int threshold) {
		if (threshold <= 0)
			throw new IllegalArgumentException("Threshold must be positive."); //$NON-NLS-1$
		this.importOnDemandThreshold= threshold;
	}

	 /**
	 *	Sets the on-demand import threshold for static imports.
	 *	This threshold defines the number of imports that need to be in a group to use
	 * a on-demand (star) import declaration instead.
	 *
	 * @param threshold a positive number defining the on-demand import threshold
	 * for normal (non-static) imports.
	 * @throws IllegalArgumentException a {@link IllegalArgumentException} is thrown
	 * if the number is not positive.
     */
	public void setStaticOnDemandImportThreshold(int threshold) {
		if (threshold <= 0)
			throw new IllegalArgumentException("Threshold must be positive."); //$NON-NLS-1$
		this.staticImportOnDemandThreshold= threshold;
	}

	/**
	 * The compilation unit for which this import rewrite was created for.
	 * @return the compilation unit for which this import rewrite was created for.
	 */
	public ICompilationUnit getCompilationUnit() {
		return this.compilationUnit;
	}

	/**
	 * Returns the default rewrite context that only knows about the imported types. Clients
	 * can write their own context and use the default context for the default behavior.
	 * @return the default import rewrite context.
	 */
	public ImportRewriteContext getDefaultImportRewriteContext() {
		return this.defaultContext;
	}

	/**
	 * Specifies that implicit imports (for types in <code>java.lang</code>, types in the same package as the rewrite
	 * compilation unit, and types in the compilation unit's main type) should not be created, except if necessary to
	 * resolve an on-demand import conflict.
	 * <p>
	 * The filter is enabled by default.
	 * </p>
	 * <p>
	 * Note: {@link #setUseContextToFilterImplicitImports(boolean)} can be used to filter implicit imports
	 * when a context is used.
	 * </p>
	 * 
	 * @param filterImplicitImports
	 *            if <code>true</code>, implicit imports will be filtered
	 * 
	 * @see #setUseContextToFilterImplicitImports(boolean)
	 */
	public void setFilterImplicitImports(boolean filterImplicitImports) {
		this.filterImplicitImports= filterImplicitImports;
	}

	/**
	* Sets whether a context should be used to properly filter implicit imports.
	* <p>
	* By default, the option is disabled to preserve pre-3.6 behavior.
	* </p>
	* <p>
	* When this option is set, the context passed to the <code>addImport*(...)</code> methods is used to determine
	* whether an import can be filtered because the type is implicitly visible. Note that too many imports
	* may be kept if this option is set and <code>addImport*(...)</code> methods are called without a context.
	* </p>
	* 
	* @param useContextToFilterImplicitImports the given setting
	* 
	* @see #setFilterImplicitImports(boolean)
	* @since 3.6
	*/
	public void setUseContextToFilterImplicitImports(boolean useContextToFilterImplicitImports) {
		this.useContextToFilterImplicitImports = useContextToFilterImplicitImports;
	}
	
	private static int compareImport(char prefix, String qualifier, String name, String curr) {
		if (curr.charAt(0) != prefix || !curr.endsWith(name)) {
			return ImportRewriteContext.RES_NAME_UNKNOWN;
		}

		curr= curr.substring(1); // remove the prefix

		if (curr.length() == name.length()) {
			if (qualifier.length() == 0) {
				return ImportRewriteContext.RES_NAME_FOUND;
			}
			return ImportRewriteContext.RES_NAME_CONFLICT;
		}
		// at this place: curr.length > name.length

		int dotPos= curr.length() - name.length() - 1;
		if (curr.charAt(dotPos) != '.') {
			return ImportRewriteContext.RES_NAME_UNKNOWN;
		}
		if (qualifier.length() != dotPos || !curr.startsWith(qualifier)) {
			return ImportRewriteContext.RES_NAME_CONFLICT;
		}
		return ImportRewriteContext.RES_NAME_FOUND;
	}

	/**
	 * Not API, package visibility as accessed from an anonymous type
	 */
	/* package */ final int findInImports(String qualifier, String name, int kind) {
		boolean allowAmbiguity=  (kind == ImportRewriteContext.KIND_STATIC_METHOD) || (name.length() == 1 && name.charAt(0) == '*');
		List imports= this.existingImports;
		char prefix= (kind == ImportRewriteContext.KIND_TYPE) ? NORMAL_PREFIX : STATIC_PREFIX;

		for (int i= imports.size() - 1; i >= 0 ; i--) {
			String curr= (String) imports.get(i);
			int res= compareImport(prefix, qualifier, name, curr);
			if (res != ImportRewriteContext.RES_NAME_UNKNOWN) {
				if (!allowAmbiguity || res == ImportRewriteContext.RES_NAME_FOUND) {
					if (prefix != STATIC_PREFIX) {
						return res;
					}
					Object currKind = this.importsKindMap.get(curr.substring(1));
					if (currKind != null && currKind.equals(this.importsKindMap.get(qualifier + '.' + name))) {
						return res;
					}
				}
			}
		}

		String packageName= this.compilationUnit.getParent().getElementName();
		if (kind == ImportRewriteContext.KIND_TYPE) {
			if (this.filterImplicitImports && this.useContextToFilterImplicitImports) {
				String mainTypeSimpleName= JavaCore.removeJavaLikeExtension(this.compilationUnit.getElementName());
				String mainTypeName= Util.concatenateName(packageName, mainTypeSimpleName, '.');
				if (qualifier.equals(packageName)
						|| mainTypeName.equals(Util.concatenateName(qualifier, name, '.'))) {
					return ImportRewriteContext.RES_NAME_FOUND;
				}
				
				if (this.astRoot != null) {
					List<AbstractTypeDeclaration> types = this.astRoot.types();
					int nTypes = types.size();
					for (int i = 0; i < nTypes; i++) {
						AbstractTypeDeclaration type = types.get(i);
						SimpleName simpleName = type.getName();
						if (simpleName.getIdentifier().equals(name)) { 
							return qualifier.equals(packageName)
									? ImportRewriteContext.RES_NAME_FOUND
									: ImportRewriteContext.RES_NAME_CONFLICT;
						}
					}
				} else {
					try {
						IType[] types = this.compilationUnit.getTypes();
						int nTypes = types.length;
						for (int i = 0; i < nTypes; i++) {
							IType type = types[i];
							String typeName = type.getElementName();
							if (typeName.equals(name)) {
								return qualifier.equals(packageName)
										? ImportRewriteContext.RES_NAME_FOUND
										: ImportRewriteContext.RES_NAME_CONFLICT;
							}
						}
					} catch (JavaModelException e) {
						// don't want to throw an exception here
					}
				}
			}
		}

		return ImportRewriteContext.RES_NAME_UNKNOWN;
	}

	/**
	 * Adds the necessary imports for the given annotation binding to the rewriter's record
	 * and returns an {@link Annotation} that can be used in the code.
	 * <p>
	 * No imports are added for types that are already known. If an import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records newly added imports.
	 * </p>
	 * @param annotation the annotation to be added
	 * @param ast the AST to create the returned annotation for
	 * @param context an optional context that knows about types visible in the current scope or <code>null</code>
	 * to use the default context (only using the available imports)
	 * @return an annotation node. The returned annotation contains unqualified type names where
	 * an import could be added or was already known. Type names are fully qualified if an import conflict prevented an import.
	 * 
	 * @since 3.10
	 */
	public Annotation addAnnotation(IAnnotationBinding annotation, AST ast, ImportRewriteContext context) {
		Type type = addImport(annotation.getAnnotationType(), ast, context, TypeLocation.OTHER);
		Name name;
		if (type instanceof SimpleType) {
			SimpleType simpleType = (SimpleType) type;
			name = simpleType.getName();
			// cut 'name' loose from its parent, so that it can be reused
			simpleType.setName(ast.newName("a")); //$NON-NLS-1$
		} else {
			name = ast.newName("invalid"); //$NON-NLS-1$
		}

		IMemberValuePairBinding[] mvps= annotation.getDeclaredMemberValuePairs();
		if (mvps.length == 0) {
			MarkerAnnotation result = ast.newMarkerAnnotation();
			result.setTypeName(name);
			return result;
		} else if (mvps.length == 1 && "value".equals(mvps[0].getName())) { //$NON-NLS-1$
			SingleMemberAnnotation result= ast.newSingleMemberAnnotation();
			result.setTypeName(name);
			Object value = mvps[0].getValue();
			if (value != null)
				result.setValue(addAnnotation(ast, value, context));
			return result;
		} else {
			NormalAnnotation result = ast.newNormalAnnotation();
			result.setTypeName(name);
			for (int i= 0; i < mvps.length; i++) {
				IMemberValuePairBinding mvp = mvps[i];
				MemberValuePair mvpNode = ast.newMemberValuePair();
				mvpNode.setName(ast.newSimpleName(mvp.getName()));
				Object value = mvp.getValue();
				if (value != null)
					mvpNode.setValue(addAnnotation(ast, value, context));
				result.values().add(mvpNode);
			}
			return result;
		}
	}

	/**
	 * Adds a new import to the rewriter's record and returns a {@link Type} node that can be used
	 * in the code as a reference to the type. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param typeSig the signature of the type to be added.
	 * @param ast the AST to create the returned type for.
	 * @return a type node for the given type signature. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 */
	public Type addImportFromSignature(String typeSig, AST ast) {
		return addImportFromSignature(typeSig, ast, this.defaultContext);
	}

	/**
	 * Adds a new import to the rewriter's record and returns a {@link Type} node that can be used
	 * in the code as a reference to the type. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param typeSig the signature of the type to be added.
	 * @param ast the AST to create the returned type for.
	 * @param context an optional context that knows about types visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @return a type node for the given type signature. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 */
	public Type addImportFromSignature(String typeSig, AST ast, ImportRewriteContext context) {
		if (typeSig == null || typeSig.length() == 0) {
			throw new IllegalArgumentException("Invalid type signature: empty or null"); //$NON-NLS-1$
		}
		int sigKind= Signature.getTypeSignatureKind(typeSig);
		switch (sigKind) {
			case Signature.BASE_TYPE_SIGNATURE:
				return ast.newPrimitiveType(PrimitiveType.toCode(Signature.toString(typeSig)));
			case Signature.ARRAY_TYPE_SIGNATURE:
				Type elementType= addImportFromSignature(Signature.getElementType(typeSig), ast, context);
				return ast.newArrayType(elementType, Signature.getArrayCount(typeSig));
			case Signature.CLASS_TYPE_SIGNATURE:
				String erasureSig= Signature.getTypeErasure(typeSig);

				String erasureName= Signature.toString(erasureSig);
				if (erasureSig.charAt(0) == Signature.C_RESOLVED) {
					erasureName= internalAddImport(erasureName, context);
				}
				Type baseType= ast.newSimpleType(ast.newName(erasureName));
				String[] typeArguments= Signature.getTypeArguments(typeSig);
				if (typeArguments.length > 0) {
					ParameterizedType type= ast.newParameterizedType(baseType);
					List argNodes= type.typeArguments();
					for (int i= 0; i < typeArguments.length; i++) {
						String curr= typeArguments[i];
						if (containsNestedCapture(curr)) { // see bug 103044
							argNodes.add(ast.newWildcardType());
						} else {
							argNodes.add(addImportFromSignature(curr, ast, context));
						}
					}
					return type;
				}
				return baseType;
			case Signature.TYPE_VARIABLE_SIGNATURE:
				return ast.newSimpleType(ast.newSimpleName(Signature.toString(typeSig)));
			case Signature.WILDCARD_TYPE_SIGNATURE:
				WildcardType wildcardType= ast.newWildcardType();
				char ch= typeSig.charAt(0);
				if (ch != Signature.C_STAR) {
					Type bound= addImportFromSignature(typeSig.substring(1), ast, context);
					wildcardType.setBound(bound, ch == Signature.C_EXTENDS);
				}
				return wildcardType;
			case Signature.CAPTURE_TYPE_SIGNATURE:
				return addImportFromSignature(typeSig.substring(1), ast, context);
			default:
				throw new IllegalArgumentException("Unknown type signature kind: " + typeSig); //$NON-NLS-1$
		}
	}



	/**
	 * Adds a new import to the rewriter's record and returns a type reference that can be used
	 * in the code. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored. Type annotations are ignored.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding the signature of the type to be added.
	 * @return a type reference for the given type binding. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 */
	public String addImport(ITypeBinding binding) {
		return addImport(binding, this.defaultContext);
	}

	/**
	 * Adds a new import to the rewriter's record and returns a type reference that can be used
	 * in the code. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored. Type annotations are ignored.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding the signature of the type to be added.
	 * @param context an optional context that knows about types visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @return a type reference for the given type binding. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 */
	public String addImport(ITypeBinding binding, ImportRewriteContext context) {
		if (binding.isPrimitive() || binding.isTypeVariable() || binding.isRecovered()) {
			return binding.getName();
		}

		ITypeBinding normalizedBinding= normalizeTypeBinding(binding);
		if (normalizedBinding == null) {
			return "invalid"; //$NON-NLS-1$
		}
		if (normalizedBinding.isWildcardType()) {
			StringBuffer res= new StringBuffer("?"); //$NON-NLS-1$
			ITypeBinding bound= normalizedBinding.getBound();
			if (bound != null && !bound.isWildcardType() && !bound.isCapture()) { // bug 95942
				if (normalizedBinding.isUpperbound()) {
					res.append(" extends "); //$NON-NLS-1$
				} else {
					res.append(" super "); //$NON-NLS-1$
				}
				res.append(addImport(bound, context));
			}
			return res.toString();
		}

		if (normalizedBinding.isArray()) {
			StringBuffer res= new StringBuffer(addImport(normalizedBinding.getElementType(), context));
			for (int i= normalizedBinding.getDimensions(); i > 0; i--) {
				res.append("[]"); //$NON-NLS-1$
			}
			return res.toString();
		}

		String qualifiedName= getRawQualifiedName(normalizedBinding);
		if (qualifiedName.length() > 0) {
			String str= internalAddImport(qualifiedName, context);

			ITypeBinding[] typeArguments= normalizedBinding.getTypeArguments();
			if (typeArguments.length > 0) {
				StringBuffer res= new StringBuffer(str);
				res.append('<');
				for (int i= 0; i < typeArguments.length; i++) {
					if (i > 0) {
						res.append(',');
					}
					ITypeBinding curr= typeArguments[i];
					if (containsNestedCapture(curr, false)) { // see bug 103044
						res.append('?');
					} else {
						res.append(addImport(curr, context));
					}
				}
				res.append('>');
				return res.toString();
			}
			return str;
		}
		return getRawName(normalizedBinding);
	}

	private boolean containsNestedCapture(ITypeBinding binding, boolean isNested) {
		if (binding == null || binding.isPrimitive() || binding.isTypeVariable()) {
			return false;
		}
		if (binding.isCapture()) {
			if (isNested) {
				return true;
			}
			return containsNestedCapture(binding.getWildcard(), true);
		}
		if (binding.isWildcardType()) {
			return containsNestedCapture(binding.getBound(), true);
		}
		if (binding.isArray()) {
			return containsNestedCapture(binding.getElementType(), true);
		}
		ITypeBinding[] typeArguments= binding.getTypeArguments();
		for (int i= 0; i < typeArguments.length; i++) {
			if (containsNestedCapture(typeArguments[i], true)) {
				return true;
			}
		}
		return false;
	}

	private boolean containsNestedCapture(String signature) {
		return signature.length() > 1 && signature.indexOf(Signature.C_CAPTURE, 1) != -1;
	}

	private static ITypeBinding normalizeTypeBinding(ITypeBinding binding) {
		if (binding != null && !binding.isNullType() && !"void".equals(binding.getName())) { //$NON-NLS-1$
			if (binding.isAnonymous()) {
				ITypeBinding[] baseBindings= binding.getInterfaces();
				if (baseBindings.length > 0) {
					return baseBindings[0];
				}
				return binding.getSuperclass();
			}
			if (binding.isCapture()) {
				return binding.getWildcard();
			}
			return binding;
		}
		return null;
	}

	/**
	 * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
	 * in the code. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored. If type annotations or type arguments are present at any point, the import is added up to that point and 
	 * the type is retained from that point with type annotations and type arguments.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding the signature of the type to be added.
	 * @param ast the AST to create the returned type for.
	 * @return a type node for the given type binding. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 */
	public Type addImport(ITypeBinding binding, AST ast) {
		return addImport(binding, ast, this.defaultContext, TypeLocation.UNKNOWN);
	}

	/**
	 * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
	 * in the code. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored. If type annotations or type arguments are present at any point, the import is added up to that point and 
	 * the type is retained from that point with type annotations and type arguments
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding the signature of the type to be added.
	 * @param ast the AST to create the returned type for.
	 * @param context an optional context that knows about types visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @return a type node for the given type binding. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 */
	public Type addImport(ITypeBinding binding, AST ast, ImportRewriteContext context) {
		return addImport(binding, ast, context, TypeLocation.UNKNOWN);
	}

	/**
	 * Adds a new import to the rewriter's record and returns a {@link Type} that can be used
	 * in the code. The type binding can be an array binding, type variable or wildcard.
	 * If the binding is a generic type, the type parameters are ignored. For parameterized types, also the type
	 * arguments are processed and imports added if necessary. Anonymous types inside type arguments are normalized to their base type, wildcard
	 * of wildcards are ignored. If type annotations or type arguments are present at any point, the import is added up to that point and 
	 * the type is retained from that point with type annotations and type arguments
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding the signature of the type to be added.
	 * @param ast the AST to create the returned type for.
	 * @param context an optional context that knows about types visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @param location where the type will be used. This information is needed to filter unwanted (nullness) type annotations.
	 * @return a type node for the given type binding. Type names are simple names if an import could be used,
	 * or else qualified names if an import conflict prevented an import.
	 * @since 3.13
	 */
	public Type addImport(ITypeBinding binding, AST ast, ImportRewriteContext context, TypeLocation location) {	
		ITypeBinding bindingPoint = checkAnnotationAndGenerics(binding);
		Type type = internalAddImport(bindingPoint == null ? binding : bindingPoint, ast, context, null, /* getBase */ true, bindingPoint != null && !bindingPoint.equals(binding) ? TypeLocation.OTHER : location);
		if (bindingPoint != null && !bindingPoint.equals(binding)) {
			type = buildType(binding, bindingPoint, ast, context, type, location);
		}
		return type;
	}

	/**
	 * Adds a new import to the rewriter's record and returns a type reference that can be used
	 * in the code. The type binding can only be an array or non-generic type.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param qualifiedTypeName the qualified type name of the type to be added
	 * @param context an optional context that knows about types visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @return a type reference for the given qualified type name. The type name is a simple name if an import could be used,
	 * or else a qualified name if an import conflict prevented an import.
	 */
	public String addImport(String qualifiedTypeName, ImportRewriteContext context) {
		int angleBracketOffset= qualifiedTypeName.indexOf('<');
		if (angleBracketOffset != -1) {
			return internalAddImport(qualifiedTypeName.substring(0, angleBracketOffset), context) + qualifiedTypeName.substring(angleBracketOffset);
		}
		int bracketOffset= qualifiedTypeName.indexOf('[');
		if (bracketOffset != -1) {
			return internalAddImport(qualifiedTypeName.substring(0, bracketOffset), context) + qualifiedTypeName.substring(bracketOffset);
		}
		return internalAddImport(qualifiedTypeName, context);
	}

	/**
	 * Adds a new import to the rewriter's record and returns a type reference that can be used
	 * in the code. The type binding can only be an array or non-generic type.
	 * 	<p>
 	 * No imports are added for types that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param qualifiedTypeName the qualified type name of the type to be added
	 * @return a type reference for the given qualified type name. The type name is a simple name if an import could be used,
	 * or else a qualified name if an import conflict prevented an import.
	 */
	public String addImport(String qualifiedTypeName) {
		return addImport(qualifiedTypeName, this.defaultContext);
	}

	/**
	 * Adds a new static import to the rewriter's record and returns a name - single member name if
	 * import is successful, else qualified name.
	 * 	<p>
 	 * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding The binding of the static field or method to be added.
	 * @return either the simple member name if the import was successful or else the qualified name if
	 * an import conflict prevented the import
	 * @throws IllegalArgumentException an {@link IllegalArgumentException} is thrown if the binding is not a static field
	 * or method.
	 */
	public String addStaticImport(IBinding binding) {
		return addStaticImport(binding, this.defaultContext);
	}

	/**
	 * Adds a new static import to the rewriter's record and returns a name - single member name if
	 * import is successful, else qualified name.
	 * 	<p>
 	 * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param binding The binding of the static field or method to be added.
	 * @param context an optional context that knows about members visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @return either the simple member name if the import was successful or else the qualified name if
	 * an import conflict prevented the import
	 * @throws IllegalArgumentException an {@link IllegalArgumentException} is thrown if the binding is not a static field
	 * or method.
	 */
	public String addStaticImport(IBinding binding, ImportRewriteContext context) {
		if (Modifier.isStatic(binding.getModifiers())) {
			if (binding instanceof IVariableBinding) {
				IVariableBinding variableBinding= (IVariableBinding) binding;
				if (variableBinding.isField()) {
					ITypeBinding declaringType= variableBinding.getDeclaringClass();
					return addStaticImport(getRawQualifiedName(declaringType), binding.getName(), true, context);
				}
			} else if (binding instanceof IMethodBinding) {
				ITypeBinding declaringType= ((IMethodBinding) binding).getDeclaringClass();
				return addStaticImport(getRawQualifiedName(declaringType), binding.getName(), false, context);
			}
		}
		throw new IllegalArgumentException("Binding must be a static field or method."); //$NON-NLS-1$
	}

	/**
	 * Adds a new static import to the rewriter's record and returns a name - single member name if
	 * import is successful, else qualified name.
	 * 	<p>
 	 * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param declaringTypeName The qualified name of the static's member declaring type
	 * @param simpleName the simple name of the member; either a field or a method name.
	 * @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
	 * method.
	 * @return either the simple member name if the import was successful or else the qualified name if
	 * an import conflict prevented the import
	 */
	public String addStaticImport(String declaringTypeName, String simpleName, boolean isField) {
		return addStaticImport(declaringTypeName, simpleName, isField, this.defaultContext);
	}

	/**
	 * Adds a new static import to the rewriter's record and returns a name - single member name if
	 * import is successful, else qualified name.
	 * 	<p>
 	 * No imports are added for members that are already known. If a import for a type is recorded to be removed, this record is discarded instead.
	 * </p>
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been added.
	 * </p>
	 * @param declaringTypeName The qualified name of the static's member declaring type
	 * @param simpleName the simple name of the member; either a field or a method name.
	 * @param isField <code>true</code> specifies that the member is a field, <code>false</code> if it is a
	 * method.
	 * @param context an optional context that knows about members visible in the current scope or <code>null</code>
	 * to use the default context only using the available imports.
	 * @return either the simple member name if the import was successful or else the qualified name if
	 * an import conflict prevented the import
	 */
	public String addStaticImport(String declaringTypeName, String simpleName, boolean isField, ImportRewriteContext context) {
		String key = declaringTypeName + '.' + simpleName;
		if (declaringTypeName.indexOf('.') == -1) {
			return key;
		}
		if (context == null) {
			context= this.defaultContext;
		}
		int kind= isField ? ImportRewriteContext.KIND_STATIC_FIELD : ImportRewriteContext.KIND_STATIC_METHOD;
		this.importsKindMap.put(key, Integer.valueOf(kind));
		int res= context.findInContext(declaringTypeName, simpleName, kind);
		if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
			return key;
		}
		if (res == ImportRewriteContext.RES_NAME_UNKNOWN) {
			addEntry(STATIC_PREFIX + key);
		}
		if (res == ImportRewriteContext.RES_NAME_UNKNOWN_NEEDS_EXPLICIT_IMPORT) {
			addEntry(STATIC_PREFIX + key);
			this.staticExplicitSimpleNames.add(simpleName);
		}
		return simpleName;
	}

	private String internalAddImport(String fullTypeName, ImportRewriteContext context) {
		int idx= fullTypeName.lastIndexOf('.');
		String typeContainerName, typeName;
		if (idx != -1) {
			typeContainerName= fullTypeName.substring(0, idx);
			typeName= fullTypeName.substring(idx + 1);
		} else {
			typeContainerName= ""; //$NON-NLS-1$
			typeName= fullTypeName;
		}

		if (typeContainerName.length() == 0 && PrimitiveType.toCode(typeName) != null) {
			return fullTypeName;
		}

		if (context == null)
			context= this.defaultContext;

		int res= context.findInContext(typeContainerName, typeName, ImportRewriteContext.KIND_TYPE);
		if (res == ImportRewriteContext.RES_NAME_CONFLICT) {
			return fullTypeName;
		}
		if (res == ImportRewriteContext.RES_NAME_UNKNOWN) {
			addEntry(NORMAL_PREFIX + fullTypeName);
		}
		if (res == ImportRewriteContext.RES_NAME_UNKNOWN_NEEDS_EXPLICIT_IMPORT) {
			addEntry(NORMAL_PREFIX + fullTypeName);
			this.typeExplicitSimpleNames.add(typeName);
		}
		return typeName;
	}

	private void addEntry(String entry) {
		this.existingImports.add(entry);

		if (this.removedImports.remove(entry)) {
			return;
		}

		this.addedImports.add(entry);
	}

	private boolean removeEntry(String entry) {
		if (this.existingImports.remove(entry)) {
			if (this.addedImports.remove(entry)) {
				return true;
			}

			this.removedImports.add(entry);

			return true;
		}
		return false;
	}

	/**
	 * Records to remove a import. No remove is recorded if no such import exists or if such an import is recorded
	 * to be added. In that case the record of the addition is discarded.
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that an import has been removed.
	 * </p>
	 * @param qualifiedName The import name to remove.
	 * @return <code>true</code> is returned of an import of the given name could be found.
	 */
	public boolean removeImport(String qualifiedName) {
		return removeEntry(NORMAL_PREFIX + qualifiedName);
	}

	/**
	 * Records to remove a static import. No remove is recorded if no such import exists or if such an import is recorded
	 * to be added. In that case the record of the addition is discarded.
	 * <p>
	 * The content of the compilation unit itself is actually not modified
	 * in any way by this method; rather, the rewriter just records that a new import has been removed.
	 * </p>
	 * @param qualifiedName The import name to remove.
	 * @return <code>true</code> is returned of an import of the given name could be found.
	 */
	public boolean removeStaticImport(String qualifiedName) {
		return removeEntry(STATIC_PREFIX + qualifiedName);
	}

	private static String getRawName(ITypeBinding normalizedBinding) {
		return normalizedBinding.getTypeDeclaration().getName();
	}

	private static String getRawQualifiedName(ITypeBinding normalizedBinding) {
		return normalizedBinding.getTypeDeclaration().getQualifiedName();
	}


	/**
	 * Converts all modifications recorded by this rewriter into an object representing the corresponding text
	 * edits to the source code of the rewrite's compilation unit. The compilation unit itself is not modified.
	 * <p>
	 * Calling this methods does not discard the modifications on record. Subsequence modifications are added
	 * to the ones already on record. If this method is called again later, the resulting text edit object will accurately
	 * reflect the net cumulative effect of all those changes.
	 * </p>
	 * @param monitor the progress monitor or <code>null</code>
	 * @return text edit object describing the changes to the document corresponding to the changes
	 * recorded by this rewriter
	 * @throws CoreException the exception is thrown if the rewrite fails.
	 */
	public final TextEdit rewriteImports(IProgressMonitor monitor) throws CoreException {

		SubMonitor subMonitor = SubMonitor.convert(monitor,
				Messages.bind(Messages.importRewrite_processDescription), 2);
		if (!hasRecordedChanges()) {
			this.createdImports= CharOperation.NO_STRINGS;
			this.createdStaticImports= CharOperation.NO_STRINGS;
			return new MultiTextEdit();
		}

		CompilationUnit usedAstRoot= this.astRoot;
		if (usedAstRoot == null) {
			ASTParser parser= ASTParser.newParser(AST.JLS10);
			parser.setSource(this.compilationUnit);
			parser.setFocalPosition(0); // reduced AST
			parser.setResolveBindings(false);
			usedAstRoot= (CompilationUnit) parser.createAST(subMonitor.split(1));
		}

		ImportRewriteConfiguration config= buildImportRewriteConfiguration();

		ImportRewriteAnalyzer computer=
			new ImportRewriteAnalyzer(this.compilationUnit, usedAstRoot, config);

		for (String addedImport : this.addedImports) {
			boolean isStatic = STATIC_PREFIX == addedImport.charAt(0);
			String qualifiedName = addedImport.substring(1);
			computer.addImport(isStatic, qualifiedName);
		}
	
		for (String removedImport : this.removedImports) {
			boolean isStatic = STATIC_PREFIX == removedImport.charAt(0);
			String qualifiedName = removedImport.substring(1);
			computer.removeImport(isStatic, qualifiedName);
		}

		for (String typeExplicitSimpleName : this.typeExplicitSimpleNames) {
			computer.requireExplicitImport(false, typeExplicitSimpleName);
		}

		for (String staticExplicitSimpleName : this.staticExplicitSimpleNames) {
			computer.requireExplicitImport(true, staticExplicitSimpleName);
		}

		ImportRewriteAnalyzer.RewriteResult result= computer.analyzeRewrite(subMonitor.split(1));

		this.createdImports= result.getCreatedImports();
		this.createdStaticImports= result.getCreatedStaticImports();

		return result.getTextEdit();
	}

	private ImportRewriteConfiguration buildImportRewriteConfiguration() {
		ImportRewriteConfiguration.Builder configBuilder;

		if (this.restoreExistingImports) {
			configBuilder= ImportRewriteConfiguration.Builder.preservingOriginalImports();
		} else {
			configBuilder= ImportRewriteConfiguration.Builder.discardingOriginalImports();
		}

		configBuilder.setImportOrder(Arrays.asList(this.importOrder));
		configBuilder.setTypeOnDemandThreshold(this.importOnDemandThreshold);
		configBuilder.setStaticOnDemandThreshold(this.staticImportOnDemandThreshold);

		configBuilder.setTypeContainerSorting(this.useContextToFilterImplicitImports ?
				ImportContainerSorting.BY_PACKAGE : ImportContainerSorting.BY_PACKAGE_AND_CONTAINING_TYPE);

		configBuilder.setStaticContainerSorting(ImportContainerSorting.BY_PACKAGE_AND_CONTAINING_TYPE);

		configBuilder.setImplicitImportIdentification(this.filterImplicitImports ?
				ImplicitImportIdentification.JAVA_LANG_AND_CU_PACKAGE : ImplicitImportIdentification.NONE);

		return configBuilder.build();
	}

	/**
	 * Returns all new non-static imports created by the last invocation of {@link #rewriteImports(IProgressMonitor)}
	 * or <code>null</code> if these methods have not been called yet.
	 * <p>
	 * 	Note that this list doesn't need to be the same as the added imports (see {@link #getAddedImports()}) as
	 * implicit imports are not created and some imports are represented by on-demand imports instead.
	 * </p>
	 * @return the created imports
	 */
	public String[] getCreatedImports() {
		return this.createdImports;
	}

	/**
	 * Returns all new static imports created by the last invocation of {@link #rewriteImports(IProgressMonitor)}
	 * or <code>null</code> if these methods have not been called yet.
	 * <p>
	 * Note that this list doesn't need to be the same as the added static imports ({@link #getAddedStaticImports()}) as
	 * implicit imports are not created and some imports are represented by on-demand imports instead.
	 * </p
	 * @return the created imports
	 */
	public String[] getCreatedStaticImports() {
		return this.createdStaticImports;
	}

	/**
	 * Returns all non-static imports that are recorded to be added.
	 *
	 * @return the imports recorded to be added.
	 */
	public String[] getAddedImports() {
		return filterFromList(this.addedImports, NORMAL_PREFIX);
	}

	/**
	 * Returns all static imports that are recorded to be added.
	 *
	 * @return the static imports recorded to be added.
	 */
	public String[] getAddedStaticImports() {
		return filterFromList(this.addedImports, STATIC_PREFIX);
	}

	/**
	 * Returns all non-static imports that are recorded to be removed.
	 *
	 * @return the imports recorded to be removed.
	 */
	public String[] getRemovedImports() {
		return filterFromList(this.removedImports, NORMAL_PREFIX);
	}

	/**
	 * Returns all static imports that are recorded to be removed.
	 *
	 * @return the static imports recorded to be removed.
	 */
	public String[] getRemovedStaticImports() {
		return filterFromList(this.removedImports, STATIC_PREFIX);
	}

	/**
	 * Returns <code>true</code> if imports have been recorded to be added or removed.
	 * @return boolean returns if any changes to imports have been recorded.
	 */
	public boolean hasRecordedChanges() {
		return !this.restoreExistingImports
				|| !this.addedImports.isEmpty()
				|| !this.removedImports.isEmpty();
	}


	private static String[] filterFromList(List<String> imports, char prefix) {
		if (imports == null) {
			return CharOperation.NO_STRINGS;
		}
		List<String> res= new ArrayList<>();
		for (String curr : imports) {
			if (prefix == curr.charAt(0)) {
				res.add(curr.substring(1));
			}
		}
		return res.toArray(new String[res.size()]);
	}

	private void annotateList(List annotations, IAnnotationBinding [] annotationBindings, AST ast,
						ImportRewriteContext context, TypeLocation location, ITypeBinding type) {
		if (context == null)
			context= this.defaultContext;
		annotationBindings = context.removeRedundantTypeAnnotations(annotationBindings, location, type);
		for (int i = 0; i< annotationBindings.length; i++) {
			Annotation annotation = addAnnotation(annotationBindings[i], ast, context);
			if (annotation != null) annotations.add(annotation);
		}
	}

	private Type annotateType(ITypeBinding binding, AST ast, ImportRewriteContext context, Type type, TypeLocation location) {
		IAnnotationBinding [] annotationBindings = binding.getTypeAnnotations();
		if (annotationBindings != null && annotationBindings.length > 0 && type instanceof AnnotatableType) {
			annotateList(((AnnotatableType) type).annotations(), annotationBindings, ast, context, location, binding);
		}
		return type;
	}

	private Type buildType(ITypeBinding binding, ITypeBinding bindingPoint, AST ast, ImportRewriteContext context, Type qualifier, TypeLocation location) {
		if (binding.equals(bindingPoint)) {
			return qualifier;
		}
		// build the type recursively from left to right
		Type type = binding.isMember() ? buildType(binding.getDeclaringClass(), bindingPoint, ast, context, qualifier, TypeLocation.OTHER) : null;
		type = internalAddImport(binding, ast, context, type, false, location);
		return type;
	}

	private ITypeBinding checkAnnotationAndGenerics(ITypeBinding binding) {
		ITypeBinding bindingPoint = null;
		while (binding != null) {
			IAnnotationBinding annotationBinding [] = binding.getTypeAnnotations();
			ITypeBinding []  typeArguments = binding.getTypeArguments();
			if ((annotationBinding != null && annotationBinding.length > 0) ||
					(typeArguments != null && typeArguments.length > 0)) {
				bindingPoint = binding;
			}
			if (binding.isMember()) {
				binding = binding.getDeclaringClass();
			} else {
				break;
			}
		}
		return bindingPoint;
	}

	private Type createBaseType(AST ast, ImportRewriteContext context, ITypeBinding normalizedBinding, TypeLocation location) {
		Type type;
		IAnnotationBinding annotationBinding [] = normalizedBinding.getTypeAnnotations();
		boolean annotsPresent = annotationBinding != null && annotationBinding.length > 0;

		String qualifiedName= getRawQualifiedName(normalizedBinding);
		String res = qualifiedName.length() > 0 ? internalAddImport(qualifiedName, context) : getRawName(normalizedBinding);
	
		if (annotsPresent) {
			int dotIndex = res != null ? res.lastIndexOf('.') : -1;
			if (dotIndex > 0) {
				Name nameQualifier = ast.newName(res.substring(0, dotIndex));
				SimpleName simpleName = ast.newSimpleName(res.substring(dotIndex + 1));
				type = ast.newNameQualifiedType(nameQualifier, simpleName);
			} else {
				type = ast.newSimpleType(ast.newName(res));
			}
			annotateList(((AnnotatableType) type).annotations(), annotationBinding, ast, context, location, normalizedBinding);
		} else {
			type = ast.newSimpleType(ast.newName(res));
		}
		return type;
	}

	private Type getArrayType(Type elementType, AST ast, ImportRewriteContext context, ITypeBinding normalizedBinding, TypeLocation location) {
		int noDimensions = normalizedBinding.getDimensions();
		ArrayType arrayType = ast.newArrayType(elementType, noDimensions);
		if (ast.apiLevel() >= JLS8_INTERNAL) {
			for (int i = 0; i < noDimensions; i++) {
				IAnnotationBinding[] typeAnnotations = normalizedBinding.getTypeAnnotations();
				if (typeAnnotations.length > 0) {
					Dimension dimension = (Dimension) arrayType.dimensions().get(i);
					annotateList(dimension.annotations(), typeAnnotations, ast, context,
							i == 0 ? location : TypeLocation.ARRAY_CONTENTS, normalizedBinding);
				}
				normalizedBinding = normalizedBinding.getComponentType();
			}
		}
		return arrayType;
	}

	private Type internalAddImport(ITypeBinding binding, AST ast, ImportRewriteContext context, Type currentType, boolean getBase, TypeLocation location) {
		Type type = null;
		ITypeBinding normalizedBinding = null;
		
		if (binding.isPrimitive()) {
			type = ast.newPrimitiveType(PrimitiveType.toCode(binding.getName()));
			normalizedBinding= binding;
		} else {
			normalizedBinding= normalizeTypeBinding(binding);
			if (normalizedBinding == null) {
				 return ast.newSimpleType(ast.newSimpleName("invalid")); //$NON-NLS-1$
			} else if (normalizedBinding.isTypeVariable()) {
					// no import
				type = ast.newSimpleType(ast.newSimpleName(binding.getName()));
			} else if (normalizedBinding.isWildcardType()) {
				WildcardType wcType= ast.newWildcardType();
				ITypeBinding bound= normalizedBinding.getBound();
				if (bound != null && !bound.isWildcardType() && !bound.isCapture()) { // bug 96942
					Type boundType= addImport(bound, ast, context, TypeLocation.TYPE_BOUND);
					wcType.setBound(boundType, normalizedBinding.isUpperbound());
				}
				type = wcType;
			} else if (normalizedBinding.isArray()) {
				Type elementType= addImport(normalizedBinding.getElementType(), ast, context, TypeLocation.ARRAY_CONTENTS);
				type = getArrayType(elementType, ast, context, normalizedBinding, location);
			}
		}

		if (type != null) {
			return annotateType(normalizedBinding, ast, context, type, location);
		}

		if (getBase) {
			type = createBaseType(ast, context, normalizedBinding, location);
		} else  {
			type = currentType != null ? (Type) ast.newQualifiedType(currentType, ast.newSimpleName(getRawName(normalizedBinding))) : 
				ast.newSimpleType(ast.newName(getRawName(normalizedBinding)));
			type = annotateType(normalizedBinding, ast, context, type, location);
		}

		ITypeBinding[] typeArguments = normalizedBinding.getTypeArguments();
		if (typeArguments.length > 0) {
			ParameterizedType paramType = ast.newParameterizedType(type);
			List arguments = paramType.typeArguments();
			for (int i = 0; i < typeArguments.length; i++) {
				ITypeBinding curr = typeArguments[i];
				if (containsNestedCapture(curr, false)) { // see bug 103044
					arguments.add(ast.newWildcardType());
				} else {
					arguments.add(addImport(curr, ast, context, TypeLocation.TYPE_ARGUMENT));
				}
			}
			type = paramType;
		}
		return type;
	}

	private Expression addAnnotation(AST ast, Object value, ImportRewriteContext context) {
		if (value instanceof Boolean) {
			return ast.newBooleanLiteral(((Boolean) value).booleanValue());
		} else if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long
				|| value instanceof Float || value instanceof Double) {
			return ast.newNumberLiteral(value.toString());
		} else if (value instanceof Character) {
			CharacterLiteral result = ast.newCharacterLiteral();
			result.setCharValue(((Character) value).charValue());
			return result;
		} else if (value instanceof ITypeBinding) {
			TypeLiteral result = ast.newTypeLiteral();
			result.setType(addImport((ITypeBinding) value, ast, context, TypeLocation.OTHER));
			return result;
		} else if (value instanceof String) {
			StringLiteral result = ast.newStringLiteral();
			result.setLiteralValue((String) value);
			return result;
		} else if (value instanceof IVariableBinding) {
			IVariableBinding variable = (IVariableBinding) value;

			FieldAccess result = ast.newFieldAccess();
			result.setName(ast.newSimpleName(variable.getName()));
			Type type = addImport(variable.getType(), ast, context, TypeLocation.OTHER); // ignore annotations, type will discarded
			Name name;
			if (type instanceof SimpleType) {
				SimpleType simpleType = (SimpleType) type;
				name = simpleType.getName();
				// cut 'name' loose from its parent, so that it can be reused
				simpleType.setName(ast.newSimpleName("a")); //$NON-NLS-1$
			} else {
				name = ast.newName("invalid"); //$NON-NLS-1$
			}
			result.setExpression(name);
			return result;
		} else if (value instanceof IAnnotationBinding) {
			return addAnnotation((IAnnotationBinding) value, ast, context);
		} else if (value instanceof Object[]) {
			Object[] values = (Object[]) value;
			if (values.length == 1)
				return addAnnotation(ast, values[0], context);

			ArrayInitializer initializer = ast.newArrayInitializer();
			List expressions = initializer.expressions();
			int size = values.length;
			for (int i = 0; i < size; i++)
				expressions.add(addAnnotation(ast, values[i], context));
			return initializer;
		} else {
			return null;
		}
	}
}
