/*******************************************************************************
 * Copyright (c) 2015 GK Software AG.
 * 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:
 *     Stephan Herrmann - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.core.util;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationProvider;
import org.eclipse.jdt.internal.compiler.lookup.SignatureWrapper;
import org.eclipse.jdt.internal.core.ClasspathEntry;
import org.eclipse.jdt.internal.core.util.KeyToSignature;

/**
 * Utilities for accessing and manipulating text files that externally define annotations for a given Java type.
 * Files are assumed to be in ".eea format", a textual representation of annotated signatures of members of a given type.
 * 
 * @since 3.11
 * @noinstantiate This class is not intended to be instantiated by clients.
 */
public final class ExternalAnnotationUtil {

	/** Representation of a 'nullable' annotation, independent of the concrete annotation name used in Java sources. */
	public static final char NULLABLE = ExternalAnnotationProvider.NULLABLE;

	/** Representation of a 'nonnull' annotation, independent of the concrete annotation name used in Java sources. */
	public static final char NONNULL = ExternalAnnotationProvider.NONNULL;

	/**
	 * Represents absence of a null annotation. Useful for removing an existing null annotation.
	 * This character is used only internally, it is not part of the Eclipse External Annotation file format.
	 */
	public static final char NO_ANNOTATION = ExternalAnnotationProvider.NO_ANNOTATION;

	/** Strategy for merging a new signature with an existing (possibly annotated) signature. */
	public static enum MergeStrategy {
		/** Unconditionally replace the signature. */
		REPLACE_SIGNATURE,
		/** Override existing annotations, keeping old annotations in locations that are not annotated in the new signature. */
		OVERWRITE_ANNOTATIONS,
		/** Only add new annotations, never remove or overwrite existing annotations. */
		ADD_ANNOTATIONS
	}

	private static final int POSITION_RETURN_TYPE = -1;
	private static final int POSITION_FULL_SIGNATURE = -2;

	/**
	 * Answer the give method's signature in class file format.
	 * @param methodBinding binding representing a method
	 * @return a signature in class file format
	 */
	public static String extractGenericSignature(IMethodBinding methodBinding) {
		// Note that IMethodBinding.binding is not accessible, hence we need to recover the signature from the key:
		KeyToSignature parser = new KeyToSignature(methodBinding.getKey(), KeyToSignature.SIGNATURE, true);
		parser.parse();
		return parser.toString();
	}

	/**
	 * Answer the given types's signature in class file format.
	 * @param type binding representing a type
	 * @return a signature in class file format
	 */
	public static String extractGenericTypeSignature(ITypeBinding type) {
		KeyToSignature parser = new KeyToSignature(type.getKey(), KeyToSignature.SIGNATURE, true);
		parser.parse();
		return parser.toString();
	}

	/**
	 * Insert an encoded annotation into the given methodSignature affecting its return type.
	 * <p>
	 * This method is suitable for declaration annotations.
	 * </p>
	 * @param methodSignature a method signature in class file format
	 * @param annotation one of {@link #NULLABLE} and {@link #NONNULL}.
	 * @param mergeStrategy when passing {@link MergeStrategy#ADD_ANNOTATIONS} this method will
	 * 	refuse to overwrite any existing annotation in the specified location
	 * @return the modified method signature, or the original signature if modification would
	 *	conflict with the given merge strategy.
	 * @throws IllegalArgumentException if the method signature is malformed or its return type is not a reference type.
	 */
	public static String insertReturnAnnotation(String methodSignature, char annotation, MergeStrategy mergeStrategy) {
		int close = methodSignature.indexOf(')');
		if (close == -1 || close > methodSignature.length()-4)
			throw new IllegalArgumentException("Malformed method signature"); //$NON-NLS-1$
		switch (methodSignature.charAt(close+1)) {
			case 'L': case 'T': case '[':
				return insertAt(methodSignature, close+2, annotation, mergeStrategy);
		}
		throw new IllegalArgumentException("Return type is not a reference type"); //$NON-NLS-1$
	}

	/**
	 * Insert an encoded annotation into the given methodSignature affecting one of its parameters.
	 * <p>
	 * This method is suitable for declaration annotations.
	 * </p>
	 * @param methodSignature a method signature in class file format
	 * @param paramIdx 0-based index of the parameter to which the annotation should be attached
	 * @param annotation one of {@link #NULLABLE} and {@link #NONNULL}.
	 * @param mergeStrategy when passing {@link MergeStrategy#ADD_ANNOTATIONS} this method will
	 * 	refuse to overwrite any existing annotation in the specified location
	 * @return the modified method signature, or the original signature if modification would
	 *	conflict with the given merge strategy.
	 * @throws IllegalArgumentException if the method signature is malformed or its specified parameter type is not a reference type.
	 */
	public static String insertParameterAnnotation(String methodSignature, int paramIdx, char annotation, MergeStrategy mergeStrategy)
	{
		SignatureWrapper wrapper = new SignatureWrapper(methodSignature.toCharArray());
		wrapper.start = 1;
		for (int i = 0; i < paramIdx; i++)
			wrapper.start = wrapper.computeEnd() + 1;
		int start = wrapper.start;
		switch (methodSignature.charAt(start)) {
			case 'L': case 'T': case '[':
				return insertAt(methodSignature, start+1, annotation, mergeStrategy);
		}
		throw new IllegalArgumentException("Paramter type is not a reference type"); //$NON-NLS-1$
	}

	/**
	 * Answer the external annotation file corresponding to the given type as seen from the given project.
	 * Note that manipulation of external annotations is only supported for annotation files in the workspace,
	 * and only in directory layout, not from zip files.
	 * @param project current project that references the given type from a jar file.
	 * @param type the type for which external annotations are sought
	 * @param monitor progress monitor to be passed through into file operations
	 * @return a file assumed (but not checked) to be in .eea format. The file may not "exist".
	 * 	Can be null if the given type is not contained in a jar file for which an external annotation path
	 *  has been defined in the context of the given project.
	 * @throws CoreException Signals a problem in accessing any of the relevant elements: the project, the type,
	 * the containing jar file and finally the sought annotation file.
	 */
	public static IFile getAnnotationFile(IJavaProject project, ITypeBinding type, IProgressMonitor monitor) throws CoreException {
	
		IType targetType = project.findType(type.getErasure().getQualifiedName());
		if (!targetType.exists())
			return null;

		String binaryTypeName = targetType.getFullyQualifiedName('$').replace('.', '/');
		
		IPackageFragmentRoot packageRoot = (IPackageFragmentRoot) targetType.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
		IClasspathEntry entry = packageRoot.getResolvedClasspathEntry();
		IPath annotationPath = ClasspathEntry.getExternalAnnotationPath(entry, project.getProject(), false);
	
		if (annotationPath == null) 
			return null;
		IWorkspaceRoot workspaceRoot = project.getProject().getWorkspace().getRoot();
		IFile annotationZip = workspaceRoot.getFile(annotationPath);
		if (annotationZip.exists())
			return null;
	
		annotationPath = annotationPath.append(binaryTypeName).addFileExtension(ExternalAnnotationProvider.ANNOTION_FILE_EXTENSION);
		return workspaceRoot.getFile(annotationPath);
	}

	/**
	 * Update the given external annotation file with details regarding annotations of one specific method or field.
	 * If the specified member already has external annotations, old and new annotations will be merged,
	 * with priorities controlled by the parameter 'mergeStrategy'.
	 * <p>
	 * This method is suitable for declaration annotations and type use annotations.
	 * </p>
	 * @param typeName binary name (slash separated) of the type being annotated
	 * @param file a file assumed to be in .eea format, will be created if it doesn't exist.
	 * @param selector selector of the method or field
	 * @param originalSignature unannotated signature of the member, used for identification
	 * @param annotatedSignature new signatures whose annotations should be superimposed on the member
	 * @param mergeStrategy controls how old and new signatures should be merged
	 * @param monitor progress monitor to be passed through into file operations, or null if no reporting is desired
	 * @throws CoreException if access to the file fails
	 * @throws IOException if reading file content fails
	 */
	public static void annotateMember(String typeName, IFile file, String selector, String originalSignature, String annotatedSignature,
										MergeStrategy mergeStrategy, IProgressMonitor monitor)
			throws CoreException, IOException
	{
		annotateMember(typeName, file, selector, originalSignature, annotatedSignature, POSITION_FULL_SIGNATURE, mergeStrategy, monitor);
	}

	/**
	 * Update the given external annotation file with details regarding annotations of the return type of a given method.
	 * If the specified method already has external annotations, old and new annotations will be merged,
	 * with priorities controlled by the parameter 'mergeStrategy'.
	 * <p>
	 * This method is suitable for declaration annotations and type use annotations.
	 * </p>
	 * @param typeName binary name (slash separated) of the type being annotated
	 * @param file a file assumed to be in .eea format, will be created if it doesn't exist.
	 * @param selector selector of the method
	 * @param originalSignature unannotated signature of the member, used for identification
	 * @param annotatedReturnType signature of the new return type whose annotations should be superimposed on the method
	 * @param mergeStrategy controls how old and new signatures should be merged
	 * @param monitor progress monitor to be passed through into file operations, or null if no reporting is desired
	 * @throws CoreException if access to the file fails
	 * @throws IOException if reading file content fails
	 * @throws IllegalArgumentException if the annotatedReturnType does not structurally match to originalSignature
	 */
	public static void annotateMethodReturnType(String typeName, IFile file, String selector, String originalSignature,
										String annotatedReturnType, MergeStrategy mergeStrategy, IProgressMonitor monitor)
			throws CoreException, IOException, IllegalArgumentException
	{
		annotateMember(typeName, file, selector, originalSignature, annotatedReturnType, POSITION_RETURN_TYPE, mergeStrategy, monitor);
	}

	/**
	 * Update the given external annotation file with details regarding annotations of a parameter type of a given method.
	 * If the specified method already has external annotations, old and new annotations will be merged,
	 * with priorities controlled by the parameter 'mergeStrategy'.
	 * <p>
	 * This method is suitable for declaration annotations and type use annotations.
	 * </p>
	 * @param typeName binary name (slash separated) of the type being annotated
	 * @param file a file assumed to be in .eea format, will be created if it doesn't exist.
	 * @param selector selector of the method
	 * @param originalSignature unannotated signature of the member, used for identification
	 * @param annotatedParameterType signature of the new parameter type whose annotations should be superimposed on the method
	 * @param paramIdx 0-based index of the parameter to which the annotation should be attached
	 * @param mergeStrategy controls how old and new signatures should be merged
	 * @param monitor progress monitor to be passed through into file operations, or null if no reporting is desired
	 * @throws CoreException if access to the file fails
	 * @throws IOException if reading file content fails
	 * @throws IllegalArgumentException if the annotatedParameterType does not structurally match to originalSignature
	 */
	public static void annotateMethodParameterType(String typeName, IFile file, String selector, String originalSignature,
										String annotatedParameterType, int paramIdx, MergeStrategy mergeStrategy, IProgressMonitor monitor)
			throws CoreException, IOException, IllegalArgumentException
	{
		annotateMember(typeName, file, selector, originalSignature, annotatedParameterType, paramIdx, mergeStrategy, monitor);
	}

	private static void annotateMember(String typeName, IFile file, String selector, String originalSignature, String annotatedSignature,
										int updatePosition, MergeStrategy mergeStrategy, IProgressMonitor monitor)
			throws CoreException, IOException, IllegalArgumentException
	{

		if (!file.exists()) {
			// assemble full annotatedSignature (don't bother merging since no previous signature exists):
			annotatedSignature = updateSignature(originalSignature, annotatedSignature, updatePosition, MergeStrategy.REPLACE_SIGNATURE);

			StringBuffer newContent= new StringBuffer();
			// header:
			newContent.append(ExternalAnnotationProvider.CLASS_PREFIX);
			newContent.append(typeName).append('\n');
			// new entry:
			newContent.append(selector).append('\n');
			newContent.append(' ').append(originalSignature).append('\n');
			newContent.append(' ').append(annotatedSignature).append('\n');

			createNewFile(file, newContent.toString(), monitor);
		} else {
			BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()));
			StringBuffer newContent = new StringBuffer();
			try {
				newContent.append(reader.readLine()).append('\n'); // skip class name
				String line;
				while ((line = reader.readLine()) != null) {
					if (line.isEmpty()) {
						newContent.append('\n');
						continue;
					}
					if (!Character.isJavaIdentifierStart(line.charAt(0))) {
						newContent.append(line).append('\n');
						continue;
					}
					// compare selectors:
					int relation = line.compareTo(selector);
					if (relation > 0) { // past the insertion point
						break;
					}
					if (relation < 0) {
						newContent.append(line).append('\n');
						continue;
					}
					if (relation == 0) {
						StringBuffer pending = new StringBuffer(line).append('\n');
						pending.append(line = reader.readLine());
						if (line == null) {
							break; // found only the selector at EOF, append right here, ignoring 'pending'
						}
						// compare original signatures:
						relation = line.trim().compareTo(originalSignature);
						if (relation > 0) { // past the insertion point
							// add new entry (below)
							line = pending.toString(); // push back
							break;
						}
						newContent.append(pending).append('\n');
						if (relation < 0)
							continue;
						if (relation == 0) {
							// update existing entry:
							String annotationLine = reader.readLine();
							String nextLine = null;
							if (annotationLine == null || annotationLine.isEmpty() || !annotationLine.startsWith(" ")) { //$NON-NLS-1$
								nextLine = annotationLine; // push back, since not a signature line
								annotationLine = line; // no annotated line yet, use unannotated line instead
							}
							if (annotationLine.startsWith(" ")) { //$NON-NLS-1$
								switch (mergeStrategy) {
									case REPLACE_SIGNATURE:
										break; // unconditionally use annotatedSignature
									case OVERWRITE_ANNOTATIONS:
									case ADD_ANNOTATIONS:
										annotatedSignature = updateSignature(annotationLine.trim(), annotatedSignature, updatePosition, mergeStrategy);
										break;
									default:
										JavaCore.getJavaCore().getLog().log(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID,
																				"Unexpected value for enum MergeStrategy")); //$NON-NLS-1$
								}
							}
							writeFile(file, newContent, annotatedSignature, nextLine, reader, monitor);
							return;
						}
					}
				}
				// add new entry:
				newContent.append(selector).append('\n');
				newContent.append(' ').append(originalSignature).append('\n');
				annotatedSignature = updateSignature(originalSignature, annotatedSignature, updatePosition, mergeStrategy);
				writeFile(file, newContent, annotatedSignature, line, reader, monitor);
			} finally {
				reader.close();
			}
		}
	}

	private static String updateSignature(String originalSignature, String annotatedSignature, int updatePosition, MergeStrategy mergeStrategy) {
		StringBuffer buf = new StringBuffer();
		String signatureToReplace;
		String postfix = null;
		switch (updatePosition) {
			case POSITION_FULL_SIGNATURE:
				signatureToReplace = originalSignature;
				break;
			case POSITION_RETURN_TYPE:
				assert originalSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
				int close = originalSignature.indexOf(')');
				buf.append(originalSignature, 0, close+1);
				signatureToReplace = originalSignature.substring(close+1);
				break;
			default: // parameter
				SignatureWrapper wrapper = new SignatureWrapper(originalSignature.toCharArray(), true, true); // may already contain annotations
				wrapper.start = 1;
				for (int i = 0; i < updatePosition; i++)
					wrapper.start = wrapper.computeEnd() + 1;
				int start = wrapper.start;
				int end = wrapper.computeEnd();
				end = wrapper.skipAngleContents(end);
				buf.append(originalSignature, 0, start);
				signatureToReplace = originalSignature.substring(start, end+1);
				postfix = originalSignature.substring(end+1, originalSignature.length());
		}
		updateType(buf, signatureToReplace.toCharArray(), annotatedSignature.toCharArray(), mergeStrategy);
		if (postfix != null)
			buf.append(postfix);
		return buf.toString();
	}

	/**
	 * Insert that given annotation at the given position into the given signature. 
	 * @param mergeStrategy if set to {@link MergeStrategy#ADD_ANNOTATIONS}, refuse to
	 *   overwrite any existing annotation in the specified location.
	 */
	private static String insertAt(String signature, int position, char annotation, MergeStrategy mergeStrategy) {
		StringBuffer result = new StringBuffer();
		result.append(signature, 0, position);
		result.append(annotation);
		char next = signature.charAt(position);
		switch (next) {
			case NULLABLE: case NONNULL:
				if (mergeStrategy == MergeStrategy.ADD_ANNOTATIONS)
					return signature; // refuse any change
				position++; // skip old annotation
		}
		result.append(signature, position, signature.length());
		return result.toString();
	}

	/**
	 * Update 'oldType' with annotations from 'newType' guided by 'mergeStrategy'.
	 * The result is written into 'buf' as we go.
	 */
	private static boolean updateType(StringBuffer buf, char[] oldType, char[] newType, MergeStrategy mergeStrategy) {
		if (mergeStrategy == MergeStrategy.REPLACE_SIGNATURE) {
			buf.append(newType);
			return false;
		}			
		try {
			SignatureWrapper oWrap = new SignatureWrapper(oldType, true, true); // may already contain annotations
			SignatureWrapper nWrap = new SignatureWrapper(newType, true, true); // may already contain annotations
			if (match(buf, oWrap, nWrap, 'L', false)
				|| match(buf, oWrap, nWrap, 'T', false))
			{
				mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
				buf.append(oWrap.nextName());
				nWrap.nextName(); // skip
				if (match(buf, oWrap, nWrap, '<', false)) {
					do {
						int oStart = oWrap.start;
						int nStart = nWrap.start;
						oWrap.computeEnd();
						nWrap.computeEnd();
						if (updateType(buf, oWrap.getFrom(oStart), nWrap.getFrom(nStart), mergeStrategy))
							mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
					} while (!match(buf, oWrap, nWrap, '>', false));
				}
				match(buf, oWrap, nWrap, ';', true);
			} else if (match(buf, oWrap, nWrap, '[', false)) {
				mergeAnnotation(buf, oWrap, nWrap, mergeStrategy);
				updateType(buf, oWrap.tail(), nWrap.tail(), mergeStrategy);
			} else if (match(buf, oWrap, nWrap, '*', false)
					|| match(buf, oWrap, nWrap, '+', false)
					|| match(buf, oWrap, nWrap, '-', false))
			{
				return true; // annotation allowed after this (not included in oldType / newType)
			} else {			
				buf.append(oldType);
			}
		} catch (ArrayIndexOutOfBoundsException aioobe) { // from several locations inside match() or mergeAnnotation().
			StringBuilder msg = new StringBuilder("Structural mismatch between ").append(oldType).append(" and ").append(newType); //$NON-NLS-1$ //$NON-NLS-2$
			throw new IllegalArgumentException(msg.toString(), aioobe);
		}
		return false;
	}
	/**
	 * Does the current char at both given signatures match the 'expected' char?
	 * If yes, print it into 'buf' and answer true.
	 * If no, if 'force' raise an exception, else quietly answer false without updating 'buf'.
	 */
	private static boolean match(StringBuffer buf, SignatureWrapper sig1, SignatureWrapper sig2, char expected, boolean force) {
		boolean match1 = sig1.signature[sig1.start] == expected;
		boolean match2 = sig2.signature[sig2.start] == expected;
		if (match1 != match2) {
			StringBuilder msg = new StringBuilder("Mismatching type structures ") //$NON-NLS-1$
									.append(sig1.signature).append(" vs ").append(sig2.signature); //$NON-NLS-1$
			throw new IllegalArgumentException(msg.toString()); 
		}
		if (match1) {
			buf.append(expected);
			sig1.start++;
			sig2.start++;
			return true;
		} else if (force) {
			throw new IllegalArgumentException("Expected char "+expected+" not found in "+new String(sig1.signature)); //$NON-NLS-1$ //$NON-NLS-2$
		} else {
			return false;
		}
	}

	/**
	 * If a current char of 'oldS' and/or 'newS' represents a null annotation, insert it into 'buf' guided by 'mergeStrategy'.
	 * If the new char is NO_ANNOTATION and strategy is OVERWRITE_ANNOTATIONS, silently skip over any null annotations in 'oldS'. 
	 */
	private static void mergeAnnotation(StringBuffer buf, SignatureWrapper oldS, SignatureWrapper newS, MergeStrategy mergeStrategy) {
		 // if atEnd use a char that's different from NULLABLE, NONNULL and NO_ANNOTATION:
		char oldAnn = !oldS.atEnd() ? oldS.signature[oldS.start] : '\0';
		char newAnn = !newS.atEnd() ? newS.signature[newS.start] : '\0';
		switch (mergeStrategy) {
			case ADD_ANNOTATIONS:
				switch (oldAnn) {
					case NULLABLE: case NONNULL:
						oldS.start++;
						buf.append(oldAnn); // old exists, so it remains
						switch (newAnn) { case NULLABLE: case NONNULL: newS.start++; } // just skip
						return;
				}
				//$FALL-THROUGH$
			case OVERWRITE_ANNOTATIONS:
				switch (newAnn) {
					case NULLABLE: case NONNULL:
						newS.start++;
						buf.append(newAnn); // new exists and is not suppressed by "ADD & old exists"
						switch (oldAnn) { case NULLABLE: case NONNULL: oldS.start++; } // just skip
						break;
					case NO_ANNOTATION:
						newS.start++; // don't insert
						switch (oldAnn) { case NULLABLE: case NONNULL: oldS.start++; } // just skip
						break;
					default:
						switch (oldAnn) { 
							case NULLABLE: case NONNULL: 
								oldS.start++;
								buf.append(oldAnn); // keep
						}
				}
		}
	}

	/**
	 * Write back the given annotationFile, with the following content:
	 * - head (assumed to include a member and its original signature
	 * - annotatedSignature
	 * - nextLines (optionally, may be null)
	 * - the still unconsumed content of tailReader
	 */
	private static void writeFile(IFile annotationFile, StringBuffer head, String annotatedSignature,
									String nextLines, BufferedReader tailReader, IProgressMonitor monitor)
			throws CoreException, IOException
	{
		head.append(' ').append(annotatedSignature).append('\n'); 
		if (nextLines != null)
			head.append(nextLines).append('\n');
		String line;
		while ((line = tailReader.readLine()) != null)
			head.append(line).append('\n');
		ByteArrayInputStream newContent = new ByteArrayInputStream(head.toString().getBytes("UTF-8")); //$NON-NLS-1$
		annotationFile.setContents(newContent, IResource.KEEP_HISTORY, monitor);
	}

	private static void createNewFile(IFile file, String newContent, IProgressMonitor monitor) throws CoreException {
		ensureExists(file.getParent(), monitor);
		
		try {
			file.create(new ByteArrayInputStream(newContent.getBytes("UTF-8")), false, monitor); //$NON-NLS-1$
		} catch (UnsupportedEncodingException e) {
			throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, e.getMessage(), e));
		}
	}

	private static void ensureExists(IContainer container, IProgressMonitor monitor) throws CoreException {
		if (container.exists()) return;
		if (!(container instanceof IFolder)) throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, "not a folder: "+container)); //$NON-NLS-1$
		IContainer parent= container.getParent();
		if (parent instanceof IFolder) {
			ensureExists(parent, monitor);
		}
		((IFolder) container).create(false, true, monitor);
	}

	/**
	 * Retrieve the annotated signature of a specified member as found in the given external annotation file, if any.
	 * @param typeName fully qualified slash-separated name of the type for which the file defines external annotations
	 * @param file a file assumed to be in .eea format, must not be null, but may not exist
	 * @param selector name of the member whose annotation we are looking for
	 * @param originalSignature the unannotated signature by which the member is identified
	 * @return the annotated signature as found in the file, or null.
	 */
	public static String getAnnotatedSignature(String typeName, IFile file, String selector, String originalSignature) {
		if (file.exists()) {
			try (BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents()))) {
				ExternalAnnotationProvider.assertClassHeader(reader.readLine(), typeName);
				while (true) {
					String line = reader.readLine();
					// selector:
					if (selector.equals(line)) {
						// original signature:
						line = reader.readLine();
						if (originalSignature.equals(ExternalAnnotationProvider.extractSignature(line))) {
							// annotated signature:
							return ExternalAnnotationProvider.extractSignature(reader.readLine());
						}
					}
					if (line == null)
						break;
				}
			} catch (IOException | CoreException e) {
				return null;
			}
		}
		return null;
	}

	/**
	 * Apply the specified changes on the given type.
	 * This method can be used as a dry run without modifying an annotation file.
	 * 
	 * @param originalSignature the original type signature, may be annotated already
	 * @param annotatedType a type signature with additional annotations (incl. {@link #NO_ANNOTATION}).
	 * @param mergeStrategy controls how old and new signatures should be merged
	 * @return an array of length four: <ul>
	 * <li>prefix up-to the changed type</li>
	 * <li>original type</li>
	 * <li>changed type</li>
	 * <li>postfix after the changed type <em>(here: empty string)</li>
	 * </ul>
	 */
	public static String[] annotateType(String originalSignature, String annotatedType, MergeStrategy mergeStrategy)
	{
		String[] result = new String[4]; // prefix, orig, replacement, postfix
		StringBuffer buf;
		result[0] = ""; //$NON-NLS-1$
		buf = new StringBuffer();
		result[1] = originalSignature;
		updateType(buf, originalSignature.toCharArray(), annotatedType.toCharArray(), mergeStrategy);
		result[2] = buf.toString();
		result[3] = ""; //$NON-NLS-1$
		return result;
	}

	/**
	 * Apply the specified changes on the return type of the given signature.
	 * This method can be used as a dry run without modifying an annotation file.
	 * 
	 * @param originalSignature the original full signature, may be annotated already
	 * @param annotatedType a type signature with additional annotations (incl. {@link #NO_ANNOTATION}).
	 * @param mergeStrategy controls how old and new signatures should be merged
	 * @return an array of length four: <ul>
	 * <li>prefix up-to the changed type</li>
	 * <li>original type</li>
	 * <li>changed type</li>
	 * <li>postfix after the changed type <em>(here: empty string)</li>
	 * </ul>
	 */
	public static String[] annotateReturnType(String originalSignature, String annotatedType, MergeStrategy mergeStrategy)
	{
		String[] result = new String[4]; // prefix, orig, replacement, postfix
		StringBuffer buf;
		assert originalSignature.charAt(0) == '(' : "signature must start with '('"; //$NON-NLS-1$
		int close = originalSignature.indexOf(')');
		result[0] = originalSignature.substring(0, close+1);
		buf = new StringBuffer();
		result[1] = originalSignature.substring(close+1);
		updateType(buf, result[1].toCharArray(), annotatedType.toCharArray(), mergeStrategy);
		result[2] = buf.toString();
		result[3] = ""; //$NON-NLS-1$
		return result;
	}
	

	/**
	 * Apply the specified changes on a parameter within the given signature.
	 * This method can be used as a dry run without modifying an annotation file.
	 * 
	 * @param originalSignature the original full signature, may be annotated already
	 * @param annotatedType a type signature with additional annotations (incl. {@link #NO_ANNOTATION}).
	 * @param paramIdx the index of a parameter to annotated
	 * @param mergeStrategy controls how old and new signatures should be merged
	 * @return an array of length four: <ul>
	 * <li>prefix up-to the changed type</li>
	 * <li>original type</li>
	 * <li>changed type</li>
	 * <li>postfix after the changed type</li>
	 * </ul>
	 */
	public static String[] annotateParameterType(String originalSignature, String annotatedType, int paramIdx, MergeStrategy mergeStrategy)
	{
		String[] result = new String[4]; // prefix, orig, replacement, postfix
		StringBuffer buf;
		SignatureWrapper wrapper = new SignatureWrapper(originalSignature.toCharArray(), true, true); // may already contain annotations
		wrapper.start = 1;
		for (int i = 0; i < paramIdx; i++)
			wrapper.start = wrapper.computeEnd() + 1;
		int start = wrapper.start;
		int end = wrapper.computeEnd();
		end = wrapper.skipAngleContents(end);
		result[0] = originalSignature.substring(0, start);				
		buf = new StringBuffer();
		result[1] = originalSignature.substring(start, end+1);
		updateType(buf, result[1].toCharArray(), annotatedType.toCharArray(), mergeStrategy);
		result[2] = buf.toString();
		result[3] = originalSignature.substring(end+1, originalSignature.length());
		return result;
	}
}
