/*******************************************************************************
 * Copyright (c) 2007, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.pde.api.tools.internal;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.pde.api.tools.internal.provisional.ApiDescriptionVisitor;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.Factory;
import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
import org.eclipse.pde.api.tools.internal.provisional.IApiDescription;
import org.eclipse.pde.api.tools.internal.provisional.IApiJavadocTag;
import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IFieldDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IMethodDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IPackageDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.descriptors.IReferenceTypeDescriptor;
import org.eclipse.pde.api.tools.internal.provisional.scanner.ScannerMessages;
import org.eclipse.pde.api.tools.internal.util.Signatures;
import org.eclipse.pde.api.tools.internal.util.Util;
import org.eclipse.text.edits.TextEdit;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Provides tools for scanning/loading/parsing component.xml files.
 *
 * @since 1.0.0
 */
public class ApiDescriptionProcessor {

	/**
	 * Visits each type, collecting all members before processing the type.
	 */
	static class DescriptionVisitor extends ApiDescriptionVisitor {

		/**
		 * The API description associated with the project.
		 */
		private IApiDescription apiDescription = null;

		/**
		 * Java project to resolve types in
		 */
		private IJavaProject project = null;

		/**
		 * List to collect text edits
		 */
		private Map<IFile, Set<TextEdit>> fCollector = null;

		/**
		 * Members collected from current type.
		 */
		private List<IElementDescriptor> members = new ArrayList<>();

		/**
		 * List of exception statuses that occurred, or <code>null</code> if
		 * none.
		 */
		private List<IStatus> exceptions = null;

		/**
		 * Constructs a new visitor to collect tag updates in a java project.
		 *
		 * @param jp project to update
		 * @param cd project's API description
		 * @param collector collection to place text edits into
		 */
		DescriptionVisitor(IJavaProject jp, IApiDescription cd, Map<IFile, Set<TextEdit>> collector) {
			project = jp;
			apiDescription = cd;
			fCollector = collector;
		}

		@Override
		public boolean visitElement(IElementDescriptor element, IApiAnnotations description) {
			switch (element.getElementType()) {
				case IElementDescriptor.PACKAGE: {
					return true;
				}
				case IElementDescriptor.TYPE: {
					members.clear();
					members.add(element);
					return true;
				}
				default: {
					members.add(element);
				}
			}
			return false;
		}

		@Override
		public void endVisitElement(IElementDescriptor element, IApiAnnotations description) {
			if (element.getElementType() == IElementDescriptor.TYPE) {
				IReferenceTypeDescriptor refType = (IReferenceTypeDescriptor) element;
				try {
					IReferenceTypeDescriptor topLevelType = refType.getEnclosingType();
					while (topLevelType != null) {
						refType = topLevelType;
						topLevelType = refType.getEnclosingType();
					}
					IType type = project.findType(refType.getQualifiedName(), new NullProgressMonitor());
					IType typeInProject = Util.getTypeInSameJavaProject(type, refType.getQualifiedName(), project);
					if (typeInProject != null) {
						type = typeInProject;
					}
					if (type != null) {
						processTagUpdates(type, refType, apiDescription, members, fCollector);
					}
				} catch (CoreException e) {
					addStatus(e.getStatus());
				} catch (BadLocationException e) {
					addStatus(new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, ScannerMessages.ComponentXMLScanner_0 + element.toString(), e));
				}
				members.clear();
			}
		}

		/**
		 * Adds a status to the current listing of messages
		 *
		 * @param status
		 */
		private void addStatus(IStatus status) {
			if (exceptions == null) {
				exceptions = new ArrayList<>();
			}
			exceptions.add(status);
		}

		/**
		 * Returns the status of processing the project. Status is OK if no
		 * errors occurred.
		 *
		 * @return status
		 */
		public IStatus getStatus() {
			if (exceptions == null) {
				return Status.OK_STATUS;
			}
			return new MultiStatus(ApiPlugin.PLUGIN_ID, 0, exceptions.toArray(new IStatus[exceptions.size()]), ScannerMessages.ComponentXMLScanner_1, null);
		}

	}

	/**
	 * Visitor used for finding the nodes to update the javadoc tags for, if
	 * needed
	 */
	static class ASTTagVisitor extends ASTVisitor {
		private List<IElementDescriptor> apis = null;
		private IApiDescription description = null;
		private ASTRewrite rewrite = null;
		private Stack<Integer> typeStack;

		/**
		 * Constructor
		 *
		 * @param APIs a listing of {@link IElementDescriptor}s that we care
		 *            about for this visit
		 */
		public ASTTagVisitor(List<IElementDescriptor> apis, IApiDescription description, ASTRewrite rewrite) {
			this.apis = apis;
			this.description = description;
			this.rewrite = rewrite;
			typeStack = new Stack<>();
		}

		@Override
		public boolean visit(TypeDeclaration node) {
			int type = IApiJavadocTag.TYPE_CLASS;
			if (node.isInterface()) {
				type = IApiJavadocTag.TYPE_INTERFACE;
			}
			typeStack.push(Integer.valueOf(type));
			updateDocNode(findDescriptorByName(node.getName().getFullyQualifiedName(), null), node, getType(), IApiJavadocTag.MEMBER_NONE);
			return true;
		}

		@Override
		public void endVisit(TypeDeclaration node) {
			typeStack.pop();
		}

		/**
		 * Returns the kind of type being visited.
		 *
		 * @return <code>TYPE_CLASS</code> or <code>TYPE_INTERFACE</code>
		 */
		private int getType() {
			return (typeStack.peek()).intValue();
		}

		@Override
		public boolean visit(FieldDeclaration node) {
			List<VariableDeclarationFragment> fields = node.fragments();
			VariableDeclarationFragment fragment = null;
			for (Iterator<VariableDeclarationFragment> iter = fields.iterator(); iter.hasNext();) {
				fragment = iter.next();
				updateDocNode(findDescriptorByName(fragment.getName().getFullyQualifiedName(), null), node, getType(), IApiJavadocTag.MEMBER_FIELD);
			}
			return false;
		}

		@Override
		public boolean visit(MethodDeclaration node) {
			String signature = Signatures.getMethodSignatureFromNode(node, true);
			if (signature != null) {
				updateDocNode(findDescriptorByName(node.getName().getFullyQualifiedName(), signature), node, getType(), IApiJavadocTag.MEMBER_METHOD);
			}
			return false;
		}

		/**
		 * Updates the specified javadoc node if needed, creates a new doc node
		 * if one is not present
		 *
		 * @param element the element to get API information from
		 * @param docnode the doc node to update
		 * @param type one of <code>CLASS</code> or <code>INTERFACE</code>
		 * @param member one of <code>METHOD</code> or <code>FIELD</code> or
		 *            <code>NONE</code>
		 */
		private void updateDocNode(IElementDescriptor element, BodyDeclaration body, int type, int member) {
			if (element != null) {
				// check for missing tags first, might not need to do any work
				IApiAnnotations api = description.resolveAnnotations(element);
				if (api != null) {
					Javadoc docnode = body.getJavadoc();
					AST ast = body.getAST();
					boolean newnode = docnode == null;
					if (docnode == null) {
						docnode = ast.newJavadoc();
					}
					String[] missingtags = collectMissingTags(api, docnode.tags(), type, member);
					if (missingtags.length == 0) {
						return;
					} else if (newnode) {
						// we do not want to create a new empty Javadoc node in
						// the AST if there are no missing tags
						rewrite.set(body, body.getJavadocProperty(), docnode, null);
					}
					ListRewrite lrewrite = rewrite.getListRewrite(docnode, Javadoc.TAGS_PROPERTY);
					TagElement newtag = null;
					for (String missingtag : missingtags) {
						newtag = createNewTagElement(ast, missingtag);
						lrewrite.insertLast(newtag, null);
					}
				}
			}
		}

		/**
		 * Creates a new {@link TagElement} against the specified {@link AST}
		 * and returns it
		 *
		 * @param ast the {@link AST} to create the {@link TagElement} against
		 * @param tagname the name of the new tag
		 * @return a new {@link TagElement} with the given name
		 */
		private TagElement createNewTagElement(AST ast, String tagname) {
			TagElement newtag = ast.newTagElement();
			newtag.setTagName(tagname);
			return newtag;
		}

		/**
		 * Collects the missing javadoc tags from based on the given listing of
		 * {@link TagElement}s
		 *
		 * @param api
		 * @param tags
		 * @param type one of <code>CLASS</code> or <code>INTERFACE</code>
		 * @param member one of <code>METHOD</code> or <code>FIELD</code> or
		 *            <code>NONE</code>
		 * @return an array of the missing {@link TagElement}s or an empty
		 *         array, never <code>null</code>
		 */
		private String[] collectMissingTags(IApiAnnotations api, List<TagElement> tags, int type, int member) {
			int res = api.getRestrictions();
			ArrayList<String> missing = new ArrayList<>();
			JavadocTagManager jtm = ApiPlugin.getJavadocTagManager();
			switch (member) {
				case IApiJavadocTag.MEMBER_FIELD:
					if (RestrictionModifiers.isReferenceRestriction(res)) {
						if (!containsRestrictionTag(tags, "@noreference")) { //$NON-NLS-1$
							IApiJavadocTag tag = jtm.getTag(IApiJavadocTag.NO_REFERENCE_TAG_ID);
							missing.add(tag.getCompleteTag(type, member));
						}
					}
					break;
				case IApiJavadocTag.MEMBER_METHOD:
					if (RestrictionModifiers.isReferenceRestriction(res)) {
						if (!containsRestrictionTag(tags, "@noreference")) { //$NON-NLS-1$
							IApiJavadocTag tag = jtm.getTag(IApiJavadocTag.NO_REFERENCE_TAG_ID);
							missing.add(tag.getCompleteTag(type, member));
						}
					}
					if (RestrictionModifiers.isOverrideRestriction(res)) {
						if (!containsRestrictionTag(tags, "@nooverride")) { //$NON-NLS-1$
							IApiJavadocTag tag = jtm.getTag(IApiJavadocTag.NO_OVERRIDE_TAG_ID);
							missing.add(tag.getCompleteTag(type, member));
						}
					}
					break;
				case IApiJavadocTag.MEMBER_NONE:
					if (RestrictionModifiers.isImplementRestriction(res)) {
						if (!containsRestrictionTag(tags, "@noimplement")) { //$NON-NLS-1$
							IApiJavadocTag tag = jtm.getTag(IApiJavadocTag.NO_IMPLEMENT_TAG_ID);
							missing.add(tag.getCompleteTag(type, member));
						}
					}
					if (RestrictionModifiers.isInstantiateRestriction(res)) {
						if (!containsRestrictionTag(tags, "@noinstantiate")) { //$NON-NLS-1$
							IApiJavadocTag tag = jtm.getTag(IApiJavadocTag.NO_INSTANTIATE_TAG_ID);
							missing.add(tag.getCompleteTag(type, member));
						}
					}
					if (RestrictionModifiers.isExtendRestriction(res)) {
						if (!containsRestrictionTag(tags, "@noextend")) { //$NON-NLS-1$
							IApiJavadocTag tag = jtm.getTag(IApiJavadocTag.NO_EXTEND_TAG_ID);
							missing.add(tag.getCompleteTag(type, member));
						}
					}
					break;
				default:
					break;
			}
			return missing.toArray(new String[missing.size()]);
		}

		/**
		 * Determines if the specified tag appears in the {@link TagElement}
		 * listing given
		 *
		 * @param tags
		 * @param tag
		 * @return true if the listing of {@link TagElement}s contains the given
		 *         tag
		 */
		private boolean containsRestrictionTag(List<TagElement> tags, String tag) {
			TagElement tagelement = null;
			for (int i = 0; i < tags.size(); i++) {
				tagelement = tags.get(i);
				if (tag.equals(tagelement.getTagName())) {
					return true;
				}
			}
			return false;
		}

		/**
		 * Finds the {@link IElementDescriptor} that matches the specified name
		 * and signature
		 *
		 * @param name
		 * @param signature
		 * @return the matching {@link IElementDescriptor} or <code>null</code>
		 */
		private IElementDescriptor findDescriptorByName(String name, String signature) {
			IElementDescriptor desc = null;
			for (int i = 0; i < apis.size(); i++) {
				desc = apis.get(i);
				switch (desc.getElementType()) {
					case IElementDescriptor.TYPE: {
						if (((IReferenceTypeDescriptor) desc).getName().equals(name)) {
							return desc;
						}
						break;
					}
					case IElementDescriptor.METHOD: {
						IMethodDescriptor method = (IMethodDescriptor) desc;
						if (method.getName().equals(name) && method.getSignature().equals(signature)) {
							return desc;
						}
						break;
					}
					case IElementDescriptor.FIELD: {
						if (((IFieldDescriptor) desc).getName().equals(name)) {
							return desc;
						}
						break;
					}
					default:
						break;
				}
			}
			return null;
		}
	}

	/**
	 * Constructor can not be instantiated directly
	 */
	private ApiDescriptionProcessor() {
	}

	/**
	 * Parses a component XML into a string. The location may be a jar,
	 * directory containing the component.xml file, or the component.xml file
	 * itself
	 *
	 * @param location root location of the component.xml file, or the
	 *            component.xml file itself
	 * @return component XML as a string or <code>null</code> if none
	 * @throws IOException if unable to parse
	 */
	public static String serializeComponentXml(File location) {
		if (location.exists()) {
			ZipFile jarFile = null;
			InputStream stream = null;
			try {
				String extension = new Path(location.getName()).getFileExtension();
				if (extension != null && extension.equals("jar") && location.isFile()) { //$NON-NLS-1$
					jarFile = new ZipFile(location, ZipFile.OPEN_READ);
					ZipEntry manifestEntry = jarFile.getEntry(IApiCoreConstants.COMPONENT_XML_NAME);
					if (manifestEntry != null) {
						stream = jarFile.getInputStream(manifestEntry);
					}
				} else if (location.isDirectory()) {
					File file = new File(location, IApiCoreConstants.COMPONENT_XML_NAME);
					if (file.exists()) {
						stream = new FileInputStream(file);
					}
				} else if (location.isFile()) {
					if (location.getName().equals(IApiCoreConstants.COMPONENT_XML_NAME)) {
						stream = new FileInputStream(location);
					}
				}
				if (stream != null) {
					return new String(Util.getInputStreamAsCharArray(stream, StandardCharsets.UTF_8));
				}
			} catch (IOException e) {
				ApiPlugin.log(e);
			} finally {
				try {
					if (stream != null) {
						stream.close();
					}
				} catch (IOException e) {
					ApiPlugin.log(e);
				}
				try {
					if (jarFile != null) {
						jarFile.close();
					}
				} catch (IOException e) {
					ApiPlugin.log(e);
				}
			}
		}
		return null;
	}

	/**
	 * This method updates the javadoc for members of the specified java source
	 * files with information retrieved from the the specified component.xml
	 * file.
	 *
	 * @param project the java project to update
	 * @param componentxml the component.xml file to update from
	 * @param collector
	 * @throws CoreException
	 * @throws IOException
	 */
	public static void collectTagUpdates(IJavaProject project, File componentxml, Map<IFile, Set<TextEdit>> collector) throws CoreException, IOException {
		IApiDescription description = new ApiDescription(null);
		annotateApiSettings(project, description, serializeComponentXml(componentxml));
		// visit the types
		DescriptionVisitor visitor = new DescriptionVisitor(project, description, collector);
		description.accept(visitor, null);
		IStatus status = visitor.getStatus();
		if (!status.isOK()) {
			throw new CoreException(status);
		}
	}

	/**
	 * Given the type, the parent type descriptor and an annotated description,
	 * update the javadoc comments for the type and all members of the type
	 * found in the description.
	 *
	 * @param type
	 * @param desc
	 * @param description
	 * @param members members with API annotations
	 * @param collector
	 * @throws CoreException
	 * @throws BadLocationException
	 */
	static void processTagUpdates(IType type, IReferenceTypeDescriptor desc, IApiDescription description, List<IElementDescriptor> members, Map<IFile, Set<TextEdit>> collector) throws CoreException, BadLocationException {
		ASTParser parser = ASTParser.newParser(AST.JLS_Latest);
		ICompilationUnit cunit = type.getCompilationUnit();
		if (cunit != null) {
			parser.setSource(cunit);
			Map<String, String> options = cunit.getJavaProject().getOptions(true);
			options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
			parser.setCompilerOptions(options);
			CompilationUnit cast = (CompilationUnit) parser.createAST(new NullProgressMonitor());
			cast.recordModifications();
			ASTRewrite rewrite = ASTRewrite.create(cast.getAST());
			ASTTagVisitor visitor = new ASTTagVisitor(members, description, rewrite);
			cast.accept(visitor);
			ITextFileBufferManager bm = FileBuffers.getTextFileBufferManager();
			IPath path = cast.getJavaElement().getPath();
			try {
				bm.connect(path, LocationKind.IFILE, null);
				ITextFileBuffer tfb = bm.getTextFileBuffer(path, LocationKind.IFILE);
				IDocument document = tfb.getDocument();
				TextEdit edit = rewrite.rewriteAST(document, null);
				if (edit.getChildrenSize() > 0 || edit.getLength() != 0) {
					IFile file = (IFile) cunit.getUnderlyingResource();
					Set<TextEdit> edits = collector.get(file);
					if (edits == null) {
						edits = new HashSet<>(3);
						collector.put(file, edits);
					}
					edits.add(edit);
				}
			} finally {
				bm.disconnect(path, LocationKind.IFILE, null);
			}
		}
	}

	/**
	 * Throws an exception with the given message and underlying exception.
	 *
	 * @param message error message
	 * @param exception underlying exception, or <code>null</code>
	 * @throws CoreException
	 */
	private static void abort(String message, Throwable exception) throws CoreException {
		IStatus status = new Status(IStatus.ERROR, ApiPlugin.PLUGIN_ID, message, exception);
		throw new CoreException(status);
	}

	/**
	 * Parses the given xml document (in string format), and annotates the
	 * specified {@link IApiDescription} with {@link IPackageDescriptor}s,
	 * {@link IReferenceTypeDescriptor}s, {@link IMethodDescriptor}s and
	 * {@link IFieldDescriptor}s.
	 *
	 * @param settings API settings to annotate
	 * @param xml XML used to generate settings
	 * @throws CoreException
	 */
	public static void annotateApiSettings(IJavaProject project, IApiDescription settings, String xml) throws CoreException {
		Element root = null;
		try {
			root = Util.parseDocument(xml);
		} catch (CoreException ce) {
			abort("Failed to parse API description xml file", ce); //$NON-NLS-1$
		}
		if (!root.getNodeName().equals(IApiXmlConstants.ELEMENT_COMPONENT)) {
			abort(ScannerMessages.ComponentXMLScanner_0, null);
		}
		String version = root.getAttribute(IApiXmlConstants.ATTR_VERSION);
		ApiDescription desc = (ApiDescription) settings;
		desc.setEmbeddedVersion(version);
		// TODO for now this compares to 1.2, since the change from 1.1 -> 1.2
		// denotes the
		// @noextend change, not 1.1 -> current version
		boolean earlierversion = desc.compareEmbeddedVersionTo("1.2") == 1; //$NON-NLS-1$
		NodeList packages = root.getElementsByTagName(IApiXmlConstants.ELEMENT_PACKAGE);
		NodeList types = null;
		IPackageDescriptor packdesc = null;
		Element type = null;
		for (int i = 0; i < packages.getLength(); i++) {
			Element pkg = (Element) packages.item(i);
			// package visibility comes from the MANIFEST.MF
			String pkgName = pkg.getAttribute(IApiXmlConstants.ATTR_NAME);
			packdesc = Factory.packageDescriptor(pkgName);
			types = pkg.getElementsByTagName(IApiXmlConstants.ELEMENT_TYPE);
			for (int j = 0; j < types.getLength(); j++) {
				type = (Element) types.item(j);
				String name = type.getAttribute(IApiXmlConstants.ATTR_NAME);
				if (name.length() == 0) {
					abort("Missing type name", null); //$NON-NLS-1$
				}
				IReferenceTypeDescriptor typedesc = packdesc.getType(name);
				annotateDescriptor(project, settings, typedesc, type, earlierversion);
				annotateMethodSettings(project, settings, typedesc, type, earlierversion);
				annotateFieldSettings(project, settings, typedesc, type, earlierversion);
			}
		}
	}

	/**
	 * Annotates the backing {@link IApiDescription} from the given
	 * {@link Element}, by adding the visibility and restriction attributes to
	 * the specified {@link IElementDescriptor}
	 *
	 * @param settings the settings to annotate
	 * @param descriptor the current descriptor context
	 * @param element the current element to annotate from
	 * @param earlierversion if the version read from XML is older than the
	 *            current tooling version
	 */
	private static void annotateDescriptor(IJavaProject project, IApiDescription settings, IElementDescriptor descriptor, Element element, boolean earlierversion) {
		int typeVis = getVisibility(element);
		if (typeVis != -1) {
			settings.setVisibility(descriptor, typeVis);
		}
		settings.setRestrictions(descriptor, getRestrictions(project, element, descriptor, earlierversion));
	}

	/**
	 * Returns restriction settings described in the given element.
	 *
	 * @param project the {@link IJavaProject} context
	 * @param element XML element
	 * @param descriptor the {@link IElementDescriptor} to get the restrictions
	 *            for
	 * @param earlierversion if the version read from XML is older than the
	 *            current tooling version
	 * @return restriction settings
	 */
	private static int getRestrictions(final IJavaProject project, final Element element, final IElementDescriptor descriptor, boolean earlierversion) {
		int res = RestrictionModifiers.NO_RESTRICTIONS;
		if (element.hasAttribute(IApiXmlConstants.ATTR_RESTRICTIONS)) {
			res = Integer.parseInt(element.getAttribute(IApiXmlConstants.ATTR_RESTRICTIONS));
		} else {
			switch (descriptor.getElementType()) {
				case IElementDescriptor.FIELD: {
					res = annotateRestriction(element, IApiXmlConstants.ATTR_REFERENCE, RestrictionModifiers.NO_REFERENCE, res);
					break;
				}
				case IElementDescriptor.METHOD: {
					IMethodDescriptor method = (IMethodDescriptor) descriptor;
					res = annotateRestriction(element, IApiXmlConstants.ATTR_REFERENCE, RestrictionModifiers.NO_REFERENCE, res);
					if (!method.isConstructor()) {
						res = annotateRestriction(element, IApiXmlConstants.ATTR_OVERRIDE, RestrictionModifiers.NO_OVERRIDE, res);
					}
					break;
				}
				case IElementDescriptor.TYPE: {
					IReferenceTypeDescriptor rtype = (IReferenceTypeDescriptor) descriptor;
					res = annotateRestriction(element, IApiXmlConstants.ATTR_IMPLEMENT, RestrictionModifiers.NO_IMPLEMENT, res);
					if (earlierversion && RestrictionModifiers.isImplementRestriction(res)) {
						res |= RestrictionModifiers.NO_EXTEND;
					}
					res = annotateRestriction(element, IApiXmlConstants.ATTR_EXTEND, RestrictionModifiers.NO_EXTEND, res);
					if (!RestrictionModifiers.isExtendRestriction(res)) {
						res = annotateRestriction(element, IApiXmlConstants.ATTR_SUBCLASS, RestrictionModifiers.NO_EXTEND, res);
					}
					res = annotateRestriction(element, IApiXmlConstants.ATTR_INSTANTIATE, RestrictionModifiers.NO_INSTANTIATE, res);
					IType type = null;
					if (project != null) {
						try {
							type = project.findType(rtype.getQualifiedName());
							IType typeInProject = Util.getTypeInSameJavaProject(type, rtype.getQualifiedName(), project);
							if (typeInProject != null) {
								type = typeInProject;
							}
						} catch (JavaModelException e) {
							ApiPlugin.log("Failed to find type for " + rtype.getQualifiedName(), e); //$NON-NLS-1$
						}
						if (type != null) {
							try {
								if (Flags.isInterface(type.getFlags())) {
									res &= ~RestrictionModifiers.NO_INSTANTIATE;
								} else {
									res &= ~RestrictionModifiers.NO_IMPLEMENT;
									if (Flags.isFinal(type.getFlags())) {
										res &= ~RestrictionModifiers.NO_EXTEND;
									}
									if (Flags.isAbstract(type.getFlags())) {
										res &= ~RestrictionModifiers.NO_INSTANTIATE;
									}
								}
							} catch (JavaModelException e) {
								ApiPlugin.log("Failed to read type flags for " + type, e); //$NON-NLS-1$
							}
						}
					}
					break;
				}
				default:
					break;
			}
		}
		return res;
	}

	/**
	 * Tests if the given restriction exists for the given element and returns
	 * an updated restrictions flag.
	 *
	 * @param element XML element
	 * @param name attribute to test
	 * @param flag bit mask for attribute
	 * @param res flag to combine with
	 * @return updated flags
	 */
	private static int annotateRestriction(Element element, String name, int flag, int res) {
		String value = element.getAttribute(name);
		int lres = res;
		if (value.length() > 0) {
			if (!Boolean.parseBoolean(value)) {
				lres = res | flag;
			}
		}
		return lres;
	}

	/**
	 * Returns visibility settings described in the given element or -1 if none.
	 *
	 * @param element XML element
	 * @return visibility settings or -1 if none
	 */
	private static int getVisibility(Element element) {
		String attribute = element.getAttribute(IApiXmlConstants.ATTR_VISIBILITY);
		if (attribute != null && attribute.isEmpty()) {
			return -1;
		}
		try {
			return Integer.parseInt(attribute);
		} catch (NumberFormatException nfe) {
			if ("API".equals(attribute)) { //$NON-NLS-1$
				return VisibilityModifiers.API;
			}
			if ("PRIVATE".equals(attribute)) { //$NON-NLS-1$
				return VisibilityModifiers.PRIVATE;
			}
			if ("PRIVATE_PERMISSABLE".equals(attribute)) { //$NON-NLS-1$
				return VisibilityModifiers.PRIVATE_PERMISSIBLE;
			}
			if ("SPI".equals(attribute)) { //$NON-NLS-1$
				return VisibilityModifiers.SPI;
			}
			return -1;
		}
	}

	/**
	 * Annotates the supplied {@link IApiDescription} from all of the field
	 * elements that are direct children of the specified {@link Element}.
	 * {@link IFieldDescriptor}s are created as needed and added as children of
	 * the specified {@link IReferenceTypeDescriptor}.
	 *
	 * @param settings the {@link IApiDescription} to add the new
	 *            {@link IFieldDescriptor} to
	 * @param typedesc the containing type descriptor for this field
	 * @param type the parent {@link Element}
	 * @param earlierversion if the version read from XML is older than the
	 *            current tooling version
	 * @throws CoreException
	 */
	private static void annotateFieldSettings(IJavaProject project, IApiDescription settings, IReferenceTypeDescriptor typedesc, Element type, boolean earlierversion) throws CoreException {
		NodeList fields = type.getElementsByTagName(IApiXmlConstants.ELEMENT_FIELD);
		Element field = null;
		IFieldDescriptor fielddesc = null;
		String name = null;
		for (int i = 0; i < fields.getLength(); i++) {
			field = (Element) fields.item(i);
			name = field.getAttribute(IApiXmlConstants.ATTR_NAME);
			if (name == null) {
				abort(ScannerMessages.ComponentXMLScanner_1, null);
			}
			fielddesc = typedesc.getField(name);
			annotateDescriptor(project, settings, fielddesc, field, earlierversion);
		}
	}

	/**
	 * Annotates the supplied {@link IApiDescription} from all of the method
	 * elements that are direct children of the specified {@link Element}.
	 * {@link IMethodDescriptor}s are created as needed and added as children of
	 * the specified {@link IReferenceTypeDescriptor}.
	 *
	 * @param settings the {@link IApiDescription} to add the new
	 *            {@link IMethodDescriptor} to
	 * @param typedesc the containing type descriptor for this method
	 * @param type the parent {@link Element}
	 * @param earlierversion if the version read from XML is older than the
	 *            current tooling version
	 * @throws CoreException
	 */
	private static void annotateMethodSettings(IJavaProject project, IApiDescription settings, IReferenceTypeDescriptor typedesc, Element type, boolean earlierversion) throws CoreException {
		NodeList methods = type.getElementsByTagName(IApiXmlConstants.ELEMENT_METHOD);
		Element method = null;
		IMethodDescriptor methoddesc = null;
		String name, signature;
		for (int i = 0; i < methods.getLength(); i++) {
			method = (Element) methods.item(i);
			name = method.getAttribute(IApiXmlConstants.ATTR_NAME);
			if (name == null) {
				abort(ScannerMessages.ComponentXMLScanner_2, null);
			}
			signature = method.getAttribute(IApiXmlConstants.ATTR_SIGNATURE);
			if (signature == null) {
				abort(ScannerMessages.ComponentXMLScanner_3, null);
			}
			// old files might use '.' instead of '/'
			signature = signature.replace('.', '/');
			methoddesc = typedesc.getMethod(name, signature);
			annotateDescriptor(project, settings, methoddesc, method, earlierversion);
		}
	}
}
