/*******************************************************************************
 * Copyright (c) 2008, 2022 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
 *
 * This is an implementation of an early-draft specification developed under the Java
 * Community Process (JCP) and is made available for testing and evaluation purposes
 * only. The code is not compatible with any specification of the JCP.
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Tom Hofmann, Google <eclipse@tom.eicher.name> - [hovering] NPE when hovering over @value reference within a type's javadoc - https://bugs.eclipse.org/bugs/show_bug.cgi?id=320084
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.javadoc;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.core.runtime.Assert;
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.Path;
import org.eclipse.core.runtime.Status;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;

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.jface.internal.text.html.HTMLPrinter;

import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJarEntryResource;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IOrdinaryClassFile;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.SourceRange;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.MemberRef;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.MethodRefParameter;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TagProperty;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.core.manipulation.SharedASTProviderCore;

import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.JdtFlags;
import org.eclipse.jdt.internal.corext.util.Messages;
import org.eclipse.jdt.internal.corext.util.MethodOverrideTester;
import org.eclipse.jdt.internal.corext.util.SuperTypeHierarchyCache;

import org.eclipse.jdt.ui.JavaElementLabels;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.JavadocContentAccess;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;


/**
 * Helper to get the content of a Javadoc comment as HTML.
 *
 * <p>
 * <strong>This is work in progress. Parts of this will later become
 * API through {@link JavadocContentAccess}</strong>
 * </p>
 *
 * @since 3.4
 */
public class JavadocContentAccess2 {

	private static final String BASE_URL_COMMENT_INTRO= "<!-- baseURL=\""; //$NON-NLS-1$

	private static final String BLOCK_TAG_START= "<dl>"; //$NON-NLS-1$
	private static final String BLOCK_TAG_END= "</dl>"; //$NON-NLS-1$

	public static final String BlOCK_TAG_TITLE_START= "<dt>"; //$NON-NLS-1$
	public static final String BlOCK_TAG_TITLE_END= "</dt>"; //$NON-NLS-1$

	public static final String BlOCK_TAG_ENTRY_START= "<dd>"; //$NON-NLS-1$
	public static final String BlOCK_TAG_ENTRY_END= "</dd>"; //$NON-NLS-1$

	private static final String PARAM_NAME_START= "<b>"; //$NON-NLS-1$
	private static final String PARAM_NAME_END= "</b> "; //$NON-NLS-1$

	/**
	 * Implements the "Algorithm for Inheriting Method Comments" as specified for <a href=
	 * "http://download.oracle.com/javase/1.4.2/docs/tooldocs/solaris/javadoc.html#inheritingcomments"
	 * >1.4.2</a>, <a href=
	 * "http://download.oracle.com/javase/1.5.0/docs/tooldocs/windows/javadoc.html#inheritingcomments"
	 * >1.5</a>, and <a href=
	 * "http://download.oracle.com/javase/6/docs/technotes/tools/windows/javadoc.html#inheritingcomments"
	 * >1.6</a>.
	 *
	 * <p>
	 * Unfortunately, the implementation is broken in Javadoc implementations since 1.5, see <a
	 * href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6376959">Sun's bug</a>.
	 * </p>
	 *
	 * <p>
	 * We adhere to the spec.
	 * </p>
	 */
	private static abstract class InheritDocVisitor {
		public static final Object STOP_BRANCH= new Object() {
			@Override
			public String toString() { return "STOP_BRANCH"; } //$NON-NLS-1$
		};
		public static final Object CONTINUE= new Object() {
			@Override
			public String toString() { return "CONTINUE"; } //$NON-NLS-1$
		};

		/**
		 * Visits a type and decides how the visitor should proceed.
		 *
		 * @param currType the current type
		 * @return <ul>
		 *         <li>{@link #STOP_BRANCH} to indicate that no Javadoc has been found and visiting
		 *         super types should stop here</li>
		 *         <li>{@link #CONTINUE} to indicate that no Javadoc has been found and visiting
		 *         super types should continue</li>
		 *         <li>an {@link Object} or <code>null</code>, to indicate that visiting should be
		 *         cancelled immediately. The returned value is the result of
		 *         {@link #visitInheritDoc(IType, ITypeHierarchy)}</li>
		 *         </ul>
		 * @throws JavaModelException unexpected problem
		 * @see #visitInheritDoc(IType, ITypeHierarchy)
		 */
		public abstract Object visit(IType currType) throws JavaModelException;

		/**
		 * Visits the super types of the given <code>currentType</code>.
		 *
		 * @param currentType the starting type
		 * @param typeHierarchy a super type hierarchy that contains <code>currentType</code>
		 * @return the result from a call to {@link #visit(IType)}, or <code>null</code> if none of
		 *         the calls returned a result
		 * @throws JavaModelException unexpected problem
		 */
		public Object visitInheritDoc(IType currentType, ITypeHierarchy typeHierarchy) throws JavaModelException {
			ArrayList<IType> visited= new ArrayList<>();
			visited.add(currentType);
			Object result= visitInheritDocInterfaces(visited, currentType, typeHierarchy);
			if (result != InheritDocVisitor.CONTINUE)
				return result;

			IType superClass;
			if (currentType.isInterface())
				superClass= currentType.getJavaProject().findType("java.lang.Object"); //$NON-NLS-1$
			else
				superClass= typeHierarchy.getSuperclass(currentType);

			while (superClass != null && ! visited.contains(superClass)) {
				result= visit(superClass);
				if (result == InheritDocVisitor.STOP_BRANCH) {
					return null;
				} else if (result == InheritDocVisitor.CONTINUE) {
					visited.add(superClass);
					result= visitInheritDocInterfaces(visited, superClass, typeHierarchy);
					if (result != InheritDocVisitor.CONTINUE)
						return result;
					else
						superClass= typeHierarchy.getSuperclass(superClass);
				} else {
					return result;
				}
			}

			return null;
		}

		/**
		 * Visits the super interfaces of the given type in the given hierarchy, thereby skipping already visited types.
		 *
		 * @param visited set of visited types
		 * @param currentType type whose super interfaces should be visited
		 * @param typeHierarchy type hierarchy (must include <code>currentType</code>)
		 * @return the result, or {@link #CONTINUE} if no result has been found
		 * @throws JavaModelException unexpected problem
		 */
		private Object visitInheritDocInterfaces(ArrayList<IType> visited, IType currentType, ITypeHierarchy typeHierarchy) throws JavaModelException {
			ArrayList<IType> toVisitChildren= new ArrayList<>();
			for (IType superInterface : typeHierarchy.getSuperInterfaces(currentType)) {
				if (visited.contains(superInterface))
					continue;
				visited.add(superInterface);
				Object result= visit(superInterface);
				if (result == InheritDocVisitor.STOP_BRANCH) {
					//skip
				} else if (result == InheritDocVisitor.CONTINUE) {
					toVisitChildren.add(superInterface);
				} else {
					return result;
				}
			}
			for (IType child : toVisitChildren) {
				Object result= visitInheritDocInterfaces(visited, child, typeHierarchy);
				if (result != InheritDocVisitor.CONTINUE)
					return result;
			}
			return InheritDocVisitor.CONTINUE;
		}
	}

	private static class JavadocLookup {
		private static final JavadocLookup NONE= new JavadocLookup(null) {
			@Override
			public CharSequence getInheritedMainDescription(IMethod method) {
				return null;
			}
			@Override
			public CharSequence getInheritedParamDescription(IMethod method, int i) {
				return null;
			}
			@Override
			public CharSequence getInheritedReturnDescription(IMethod method) {
				return null;
			}
			@Override
			public CharSequence getInheritedExceptionDescription(IMethod method, String name) {
				return null;
			}
		};

		private interface DescriptionGetter {
			/**
			 * Returns a Javadoc tag description or <code>null</code>.
			 *
			 * @param contentAccess the content access
			 * @return the description, or <code>null</code> if none
			 * @throws JavaModelException unexpected problem
			 */
			CharSequence getDescription(JavadocContentAccess2 contentAccess) throws JavaModelException;
		}

		private final IType fStartingType;
		private final HashMap<IMethod, JavadocContentAccess2> fContentAccesses;

		private ITypeHierarchy fTypeHierarchy;
		private MethodOverrideTester fOverrideTester;


		private JavadocLookup(IType startingType) {
			fStartingType= startingType;
			fContentAccesses= new HashMap<>();
		}

		/**
		 * For the given method, returns the main description from an overridden method.
		 *
		 * @param method a method
		 * @return the description that replaces the <code>{&#64;inheritDoc}</code> tag,
		 * 		or <code>null</code> if none could be found
		 */
		public CharSequence getInheritedMainDescription(IMethod method) {
			return getInheritedDescription(method, JavadocContentAccess2::getMainDescription);
		}

		/**
		 * For the given method, returns the @param tag description for the given type parameter
		 * from an overridden method.
		 *
		 * @param method a method
		 * @param typeParamIndex the index of the type parameter
		 * @return the description that replaces the <code>{&#64;inheritDoc}</code> tag, or
		 *         <code>null</code> if none could be found
		 */
		public CharSequence getInheritedTypeParamDescription(IMethod method, final int typeParamIndex) {
			return getInheritedDescription(method, contentAccess -> contentAccess.getInheritedTypeParamDescription(typeParamIndex));
		}

		/**
		 * For the given method, returns the @param tag description for the given parameter from an
		 * overridden method.
		 *
		 * @param method a method
		 * @param paramIndex the index of the parameter
		 * @return the description that replaces the <code>{&#64;inheritDoc}</code> tag,
		 * 		or <code>null</code> if none could be found
		 */
		public CharSequence getInheritedParamDescription(IMethod method, final int paramIndex) {
			return getInheritedDescription(method, contentAccess -> contentAccess.getInheritedParamDescription(paramIndex));
		}

		/**
		 * For the given method, returns the @return tag description from an overridden method.
		 *
		 * @param method a method
		 * @return the description that replaces the <code>{&#64;inheritDoc}</code> tag,
		 * 		or <code>null</code> if none could be found
		 */
		public CharSequence getInheritedReturnDescription(IMethod method) {
			return getInheritedDescription(method, JavadocContentAccess2::getReturnDescription);
		}

		/**
		 * For the given method, returns the @throws/@exception tag description for the given
		 * exception from an overridden method.
		 *
		 * @param method a method
		 * @param simpleName the simple name of an exception
		 * @return the description that replaces the <code>{&#64;inheritDoc}</code> tag,
		 * 		or <code>null</code> if none could be found
		 */
		public CharSequence getInheritedExceptionDescription(IMethod method, final String simpleName) {
			return getInheritedDescription(method, contentAccess -> contentAccess.getExceptionDescription(simpleName));
		}

		private CharSequence getInheritedDescription(final IMethod method, final DescriptionGetter descriptionGetter) {
			try {
				return (CharSequence) new InheritDocVisitor() {
					@Override
					public Object visit(IType currType) throws JavaModelException {
						IMethod overridden= getOverrideTester().findOverriddenMethodInType(currType, method);
						if (overridden == null)
							return InheritDocVisitor.CONTINUE;

						JavadocContentAccess2 contentAccess= getJavadocContentAccess(overridden);
						if (contentAccess == null) {
							if (overridden.getOpenable().getBuffer() == null) {
								// Don't continue this branch when no source is available.
								// We don't extract individual tags from Javadoc attachments,
								// and it would be wrong to copy doc from further up the branch,
								// thereby skipping doc from this overridden method.
								return InheritDocVisitor.STOP_BRANCH;
							} else {
								return InheritDocVisitor.CONTINUE;
							}
						}

						CharSequence overriddenDescription= descriptionGetter.getDescription(contentAccess);
						if (overriddenDescription != null)
							return overriddenDescription;
						else
							return InheritDocVisitor.CONTINUE;
					}
				}.visitInheritDoc(method.getDeclaringType(), getTypeHierarchy());
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
			return null;
		}

		/**
		 * @param method the method
		 * @return the Javadoc content access for the given method, or
		 * 		<code>null</code> if no Javadoc could be found in source
		 * @throws JavaModelException unexpected problem
		 */
		private JavadocContentAccess2 getJavadocContentAccess(IMethod method) throws JavaModelException {
			Object cached= fContentAccesses.get(method);
			if (cached != null)
				return (JavadocContentAccess2) cached;
			if (fContentAccesses.containsKey(method))
				return null;

			IBuffer buf= method.getOpenable().getBuffer();
			if (buf == null) { // no source attachment found
				fContentAccesses.put(method, null);
				return null;
			}

			ISourceRange javadocRange= method.getJavadocRange();
			if (javadocRange == null) {
				fContentAccesses.put(method, null);
				return null;
			}

			String rawJavadoc= buf.getText(javadocRange.getOffset(), javadocRange.getLength());
			Javadoc javadoc= getJavadocNode(method, rawJavadoc);
			if (javadoc == null) {
				fContentAccesses.put(method, null);
				return null;
			}

			JavadocContentAccess2 contentAccess= new JavadocContentAccess2(method, javadoc, rawJavadoc, this);
			fContentAccesses.put(method, contentAccess);
			return contentAccess;
		}

		private ITypeHierarchy getTypeHierarchy() throws JavaModelException {
			if (fTypeHierarchy == null)
				fTypeHierarchy= SuperTypeHierarchyCache.getTypeHierarchy(fStartingType);
			return fTypeHierarchy;
		}

		private MethodOverrideTester getOverrideTester() throws JavaModelException {
			if (fOverrideTester == null)
				fOverrideTester= SuperTypeHierarchyCache.getMethodOverrideTester(fStartingType);
			return fOverrideTester;
		}
	}

	/**
	 * Either an IMember or an IPackageFragment.
	 */
	private final IJavaElement fElement;

	/**
	 * The method, or <code>null</code> if {@link #fElement} is not a method where @inheritDoc could
	 * work.
	 */
	private final IMethod fMethod;
	private final Javadoc fJavadoc;
	private final String fSource;
	private final JavadocLookup fJavadocLookup;

	private StringBuffer fBuf;
	private int fLiteralContent;
	private StringBuffer fMainDescription;
	private StringBuffer fReturnDescription;
	private StringBuffer[] fTypeParamDescriptions;
	private StringBuffer[] fParamDescriptions;
	private HashMap<String, StringBuffer> fExceptionDescriptions;

	private JavadocContentAccess2(IJavaElement element, Javadoc javadoc, String source, JavadocLookup lookup) {
		Assert.isNotNull(element);
		Assert.isTrue(element instanceof IMethod || element instanceof ILocalVariable || element instanceof ITypeParameter);
		fElement= element;
		fMethod= (IMethod) ((element instanceof ILocalVariable || element instanceof ITypeParameter) ? element.getParent() : element);
		fJavadoc= javadoc;
		fSource= source;
		fJavadocLookup= lookup;
	}

	private JavadocContentAccess2(IJavaElement element, Javadoc javadoc, String source) {
		Assert.isTrue(element instanceof IMember || element instanceof IPackageFragment || element instanceof ILocalVariable || element instanceof ITypeParameter);
		fElement= element;
		fMethod= null;
		fJavadoc= javadoc;
		fSource= source;
		fJavadocLookup= JavadocLookup.NONE;
	}

	/**
	 * Gets an IJavaElement's Javadoc comment content from the source or Javadoc attachment
	 * and renders the tags and links in HTML.
	 * Returns <code>null</code> if the element does not have a Javadoc comment or if no source is available.
	 *
	 * @param element				the element to get the Javadoc of
	 * @param useAttachedJavadoc	if <code>true</code> Javadoc will be extracted from attached Javadoc
	 * 									if there's no source
	 * @return the Javadoc comment content in HTML or <code>null</code> if the element
	 * 			does not have a Javadoc comment or if no source is available
	 * @throws CoreException is thrown when the element's Javadoc cannot be accessed
	 */
	public static String getHTMLContent(IJavaElement element, boolean useAttachedJavadoc) throws CoreException {
		if (element instanceof IPackageFragment) {
			return getHTMLContent((IPackageFragment) element);
		}
		if (element instanceof IPackageDeclaration) {
			return getHTMLContent((IPackageDeclaration) element);
		}
		if (!(element instanceof IMember)
				&& !(element instanceof ITypeParameter)
				&& (!(element instanceof ILocalVariable) || !(((ILocalVariable) element).isParameter()))) {
			return null;
		}
		String sourceJavadoc= getHTMLContentFromSource(element);
		if (sourceJavadoc == null || sourceJavadoc.length() == 0 || "{@inheritDoc}".equals(sourceJavadoc.trim())) { //$NON-NLS-1$
			if (useAttachedJavadoc) {
				if (element.getOpenable().getBuffer() == null) { // only if no source available
					return element.getAttachedJavadoc(null);
				}
				IMember member= null;
				if (element instanceof ILocalVariable) {
					member= ((ILocalVariable) element).getDeclaringMember();
				} else if (element instanceof ITypeParameter) {
					member= ((ITypeParameter) element).getDeclaringMember();
				} else if (element instanceof IMember) {
					member= (IMember) element;
				}
				if (canInheritJavadoc(member)) {
					IMethod method= (IMethod) member;
					String attachedDocInHierarchy= findAttachedDocInHierarchy(method);

					// Prepend "Overrides:" / "Specified by:" reference headers to make clear
					// that description has been copied from super method.
					if (attachedDocInHierarchy == null)
						return sourceJavadoc;
					StringBuffer superMethodReferences= createSuperMethodReferences(method);
					if (superMethodReferences == null)
						return attachedDocInHierarchy;
					superMethodReferences.append(attachedDocInHierarchy);
					return superMethodReferences.toString();
				}
			}
		}
		return sourceJavadoc;
	}

	private static StringBuffer createSuperMethodReferences(final IMethod method) throws JavaModelException {
		IType type= method.getDeclaringType();
		ITypeHierarchy hierarchy= SuperTypeHierarchyCache.getTypeHierarchy(type);
		final MethodOverrideTester tester= SuperTypeHierarchyCache.getMethodOverrideTester(type);

		final ArrayList<IMethod> superInterfaceMethods= new ArrayList<>();
		final IMethod[] superClassMethod= { null };
		new InheritDocVisitor() {
			@Override
			public Object visit(IType currType) throws JavaModelException {
				IMethod overridden= tester.findOverriddenMethodInType(currType, method);
				if (overridden == null)
					return InheritDocVisitor.CONTINUE;

				if (currType.isInterface())
					superInterfaceMethods.add(overridden);
				else
					superClassMethod[0]= overridden;

				return STOP_BRANCH;
			}
		}.visitInheritDoc(type, hierarchy);

		boolean hasSuperInterfaceMethods= !superInterfaceMethods.isEmpty();
		if (!hasSuperInterfaceMethods && superClassMethod[0] == null)
			return null;

		StringBuffer buf= new StringBuffer();
		buf.append("<div>"); //$NON-NLS-1$
		if (hasSuperInterfaceMethods) {
			buf.append("<b>"); //$NON-NLS-1$
			buf.append(JavaDocMessages.JavaDoc2HTMLTextReader_specified_by_section);
			buf.append("</b> "); //$NON-NLS-1$
			for (Iterator<IMethod> iter= superInterfaceMethods.iterator(); iter.hasNext(); ) {
				IMethod overridden= iter.next();
				buf.append(createMethodInTypeLinks(overridden));
				if (iter.hasNext())
					buf.append(JavaElementLabels.COMMA_STRING);
			}
		}
		if (superClassMethod[0] != null) {
			if (hasSuperInterfaceMethods)
				buf.append(JavaElementLabels.COMMA_STRING);
			buf.append("<b>"); //$NON-NLS-1$
			buf.append(JavaDocMessages.JavaDoc2HTMLTextReader_overrides_section);
			buf.append("</b> "); //$NON-NLS-1$
			buf.append(createMethodInTypeLinks(superClassMethod[0]));
		}
		buf.append("</div>"); //$NON-NLS-1$
		return buf;
	}

	private static String createMethodInTypeLinks(IMethod overridden) {
		CharSequence methodLink= createSimpleMemberLink(overridden);
		CharSequence typeLink= createSimpleMemberLink(overridden.getDeclaringType());
		String methodInType= MessageFormat.format(JavaDocMessages.JavaDoc2HTMLTextReader_method_in_type, methodLink, typeLink);
		return methodInType;
	}

	private static CharSequence createSimpleMemberLink(IMember member) {
		StringBuffer buf= new StringBuffer();
		buf.append("<a href='"); //$NON-NLS-1$
		try {
			String uri= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, member);
			buf.append(uri);
		} catch (URISyntaxException e) {
			JavaPlugin.log(e);
		}
		buf.append("'>"); //$NON-NLS-1$
		JavaElementLabels.getElementLabel(member, 0, buf);
		buf.append("</a>"); //$NON-NLS-1$
		return buf;
	}

	private static String getHTMLContentFromSource(IJavaElement element) throws JavaModelException {
		IMember member;
		if (element instanceof ILocalVariable) {
			member= ((ILocalVariable) element).getDeclaringMember();
		} else if (element instanceof ITypeParameter) {
			member= ((ITypeParameter) element).getDeclaringMember();
		} else if (element instanceof IMember) {
			member= (IMember) element;
		} else {
			return null;
		}

		IBuffer buf= member.getOpenable().getBuffer();
		if (buf == null) {
			return null; // no source attachment found
		}

		ISourceRange javadocRange= member.getJavadocRange();
		if (javadocRange == null) {
			if (canInheritJavadoc(member)) {
				// Try to use the inheritDoc algorithm.
				String inheritedJavadoc= javadoc2HTML(member, element, "/***/"); //$NON-NLS-1$
				if (inheritedJavadoc != null && inheritedJavadoc.length() > 0) {
					return inheritedJavadoc;
				}
			}
			return getJavaFxPropertyDoc(member);
		}

		String rawJavadoc= buf.getText(javadocRange.getOffset(), javadocRange.getLength());
		return javadoc2HTML(member, element, rawJavadoc);
	}

	private static String getJavaFxPropertyDoc(IMember member) throws JavaModelException {
		// XXX: should not do this by default (but we don't have settings for Javadoc, see https://bugs.eclipse.org/424283 )
		if (member instanceof IMethod) {
			String name= member.getElementName();
			boolean isGetter= name.startsWith("get") && name.length() > 3; //$NON-NLS-1$
			boolean isBooleanGetter= name.startsWith("is") && name.length() > 2; //$NON-NLS-1$
			boolean isSetter= name.startsWith("set") && name.length() > 3; //$NON-NLS-1$

			if (isGetter || isBooleanGetter || isSetter) {
				String propertyName= firstToLower(name.substring(isBooleanGetter ? 2 : 3));
				IType type= member.getDeclaringType();
				IMethod method= type.getMethod(propertyName + "Property", new String[0]); //$NON-NLS-1$

				if (method.exists()) {
					String content= getHTMLContentFromSource(method);
					if (content != null) {
						if (isSetter) {
							content= Messages.format(JavaDocMessages.JavadocContentAccess2_setproperty_message, new Object[] { propertyName, content });
						} else {
							content= Messages.format(JavaDocMessages.JavadocContentAccess2_getproperty_message, new Object[] { propertyName, content });
						}
					}
					return content;
				}
			} else if (name.endsWith("Property")) { //$NON-NLS-1$
				String propertyName= name.substring(0, name.length() - 8);

				IType type= member.getDeclaringType();
				IField field= type.getField(propertyName);
				if (field.exists()) {
					return getHTMLContentFromSource(field);
				}
			}
		}
		return null;
	}

	private static String firstToLower(String propertyName) {
		char[] c = propertyName.toCharArray();
		c[0] = Character.toLowerCase(c[0]);
		return String.valueOf(c);
	}

	private static Javadoc getJavadocNode(IJavaElement element, String rawJavadoc) {
		//FIXME: take from SharedASTProvider if available
		//Caveat: Javadoc nodes are not available when Javadoc processing has been disabled!
		//https://bugs.eclipse.org/bugs/show_bug.cgi?id=212207

		String source= rawJavadoc + "class C{}"; //$NON-NLS-1$
		CompilationUnit root= createAST(element, source);
		if (root == null)
			return null;
		List<AbstractTypeDeclaration> types= root.types();
		if (types.size() != 1)
			return null;
		AbstractTypeDeclaration type= types.get(0);
		return type.getJavadoc();
	}

	private static Javadoc getPackageJavadocNode(IJavaElement element, String cuSource) {
		CompilationUnit cu= createAST(element, cuSource);
		if (cu != null) {
			PackageDeclaration packDecl= cu.getPackage();
			if (packDecl != null) {
				return packDecl.getJavadoc();
			}
		}
		return null;
	}

	private static CompilationUnit createAST(IJavaElement element, String cuSource) {
		Assert.isNotNull(element);
		ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);

		IJavaProject javaProject= element.getJavaProject();
		parser.setProject(javaProject);
		Map<String, String> options= javaProject.getOptions(true);
		options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=212207
		parser.setCompilerOptions(options);

		parser.setSource(cuSource.toCharArray());
		return (CompilationUnit) parser.createAST(null);
	}

	private static String javadoc2HTML(IMember member, IJavaElement element, String rawJavadoc) {
		Javadoc javadoc= getJavadocNode(member, rawJavadoc);

		if (javadoc == null) {
			Reader contentReader= null;
			// fall back to JavadocContentAccess:
			try {
				contentReader= JavadocContentAccess.getHTMLContentReader(member, false, false);
				if (contentReader != null)
					return getString(contentReader);
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			} finally {
				if (contentReader != null) {
					try {
						contentReader.close();
					} catch (IOException e) {
						//ignore
					}
				}
			}
			return null;
		}

		if (canInheritJavadoc(member)) {
			IMethod method= (IMethod) member;
			return new JavadocContentAccess2(element, javadoc, rawJavadoc, new JavadocLookup(method.getDeclaringType())).toHTML();
		}
		return new JavadocContentAccess2(element, javadoc, rawJavadoc).toHTML();
	}

	private static boolean canInheritJavadoc(IMember member) {
		if (member instanceof IMethod && member.getJavaProject().exists()) {
			/*
			 * Exists test catches ExternalJavaProject, in which case no hierarchy can be built.
			 */
			try {
				return ! ((IMethod) member).isConstructor();
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
		return false;
	}

	/**
	 * Gets the reader content as a String
	 *
	 * @param reader the reader
	 * @return the reader content as string
	 */
	private static String getString(Reader reader) {
		StringBuilder buf= new StringBuilder();
		char[] buffer= new char[1024];
		int count;
		try {
			while ((count= reader.read(buffer)) != -1)
				buf.append(buffer, 0, count);
		} catch (IOException e) {
			return null;
		}
		return buf.toString();
	}

	/**
	 * Finds the first available attached Javadoc in the hierarchy of the given method.
	 *
	 * @param method the method
	 * @return the inherited Javadoc from the Javadoc attachment, or <code>null</code> if none
	 * @throws JavaModelException unexpected problem
	 */
	private static String findAttachedDocInHierarchy(final IMethod method) throws JavaModelException {
		IType type= method.getDeclaringType();
		ITypeHierarchy hierarchy= SuperTypeHierarchyCache.getTypeHierarchy(type);
		final MethodOverrideTester tester= SuperTypeHierarchyCache.getMethodOverrideTester(type);

		return (String) new InheritDocVisitor() {
			@Override
			public Object visit(IType currType) throws JavaModelException {
				IMethod overridden= tester.findOverriddenMethodInType(currType, method);
				if (overridden == null)
					return InheritDocVisitor.CONTINUE;

				if (overridden.getOpenable().getBuffer() == null) { // only if no source available
					String attachedJavadoc= overridden.getAttachedJavadoc(null);
					if (attachedJavadoc != null) {
						// BaseURL for the original method can be wrong for attached Javadoc from overridden
						// (e.g. when overridden is from rt.jar).
						// Fix is to store the baseURL inside the doc content and later fetch it with #extractBaseURL(String).
						String baseURL= JavaDocLocations.getBaseURL(overridden, overridden.isBinary());
						if (baseURL != null) {
							attachedJavadoc= BASE_URL_COMMENT_INTRO + baseURL + "\"--> " + attachedJavadoc; //$NON-NLS-1$
						}
						return attachedJavadoc;
					}
				}
				return CONTINUE;
			}
		}.visitInheritDoc(type, hierarchy);
	}

	private String toHTML() {
		fBuf= new StringBuffer();
		fLiteralContent= 0;

		if (fElement instanceof ILocalVariable || fElement instanceof ITypeParameter) {
			parameterToHTML();
		} else {
			elementToHTML();
		}

		String result= fBuf.toString();
		fBuf= null;
		return result;
	}

	private void parameterToHTML() {
		String elementName= fElement.getElementName();
		List<TagElement> tags= fJavadoc.tags();
		for (TagElement tag : tags) {
			String tagName= tag.getTagName();
			if (TagElement.TAG_PARAM.equals(tagName)) {
				List<? extends ASTNode> fragments= tag.fragments();
				int size= fragments.size();
				if (size > 0) {
					Object first= fragments.get(0);
					if (first instanceof SimpleName) {
						String name= ((SimpleName) first).getIdentifier();
						if (elementName.equals(name)) {
							handleContentElements(fragments.subList(1, size));
							return;
						}
					} else if (size > 2 && fElement instanceof ITypeParameter && first instanceof TextElement) {
						String firstText= ((TextElement) first).getText();
						if ("<".equals(firstText)) { //$NON-NLS-1$
							Object second= fragments.get(1);
							Object third= fragments.get(2);
							if (second instanceof SimpleName && third instanceof TextElement) {
								String name= ((SimpleName) second).getIdentifier();
								String thirdText= ((TextElement) third).getText();
								if (elementName.equals(name) && ">".equals(thirdText)) { //$NON-NLS-1$
									handleContentElements(fragments.subList(3, size));
									return;
								}
							}
						}
					}
				}
			}
		}
		if (fElement instanceof ILocalVariable) {
			List<String> parameterNames= initParameterNames();
			int i= parameterNames.indexOf(elementName);
			if (i != -1) {
				CharSequence inheritedParamDescription= fJavadocLookup.getInheritedParamDescription(fMethod, i);
				handleInherited(inheritedParamDescription);
			}
		} else if (fElement instanceof ITypeParameter) {
			List<String> typeParameterNames= initTypeParameterNames();
			int i= typeParameterNames.indexOf(elementName);
			if (i != -1) {
				CharSequence inheritedTypeParamDescription= fJavadocLookup.getInheritedTypeParamDescription(fMethod, i);
				handleInherited(inheritedTypeParamDescription);
			}
		}
	}

	private void elementToHTML() {
		// After first loop, non-null entries in the following two lists are missing and need to be inherited:
		List<String> typeParameterNames= initTypeParameterNames();
		List<String> parameterNames= initParameterNames();
		List<String> exceptionNames= initExceptionNames();

		TagElement deprecatedTag= null;
		TagElement start= null;
		List<TagElement> typeParameters= new ArrayList<>();
		List<TagElement> parameters= new ArrayList<>();
		TagElement returnTag= null;
		List<TagElement> exceptions= new ArrayList<>();
		List<TagElement> provides= new ArrayList<>();
		List<TagElement> uses= new ArrayList<>();
		List<TagElement> versions= new ArrayList<>();
		List<TagElement> authors= new ArrayList<>();
		List<TagElement> sees= new ArrayList<>();
		List<TagElement> since= new ArrayList<>();
		List<TagElement> rest= new ArrayList<>();
		List<TagElement> apinote= new ArrayList<>(1);
		List<TagElement> implspec= new ArrayList<>(1);
		List<TagElement> implnote= new ArrayList<>(1);
		List<TagElement> hidden= new ArrayList<>(1);

		List<TagElement> tags= fJavadoc.tags();
		for (TagElement tag : tags) {
			String tagName= tag.getTagName();
			if (tagName == null) {
				start= tag;

			} else {
				switch (tagName) {
					case TagElement.TAG_PARAM:
						List<? extends ASTNode> fragments= tag.fragments();
						int size= fragments.size();
						if (size > 0) {
							Object first= fragments.get(0);
							if (first instanceof SimpleName) {
								String name= ((SimpleName) first).getIdentifier();
								int paramIndex= parameterNames.indexOf(name);
								if (paramIndex != -1) {
									parameterNames.set(paramIndex, null);
								}
								parameters.add(tag);
							} else if (size > 2 && first instanceof TextElement) {
								String firstText= ((TextElement) first).getText();
								if ("<".equals(firstText)) { //$NON-NLS-1$
									Object second= fragments.get(1);
									Object third= fragments.get(2);
									if (second instanceof SimpleName && third instanceof TextElement) {
										String name= ((SimpleName) second).getIdentifier();
										String thirdText= ((TextElement) third).getText();
										if (">".equals(thirdText)) { //$NON-NLS-1$
											int paramIndex= typeParameterNames.indexOf(name);
											if (paramIndex != -1) {
												typeParameterNames.set(paramIndex, null);
											}
											typeParameters.add(tag);
										}
									}
								}
							}
						}
						break;
					case TagElement.TAG_RETURN:
						if (returnTag == null)
							returnTag= tag; // the Javadoc tool only shows the first return tag
						break;
					case TagElement.TAG_EXCEPTION:
					case TagElement.TAG_THROWS:
						exceptions.add(tag);
						List<? extends ASTNode> fragments2= tag.fragments();
						if (fragments2.size() > 0) {
							Object first= fragments2.get(0);
							if (first instanceof Name) {
								String name= ASTNodes.getSimpleNameIdentifier((Name) first);
								int exceptionIndex= exceptionNames.indexOf(name);
								if (exceptionIndex != -1) {
									exceptionNames.set(exceptionIndex, null);
								}
							}
						}
						break;
					case TagElement.TAG_PROVIDES:
						provides.add(tag);
						break;
					case TagElement.TAG_USES:
						uses.add(tag);
						break;
					case TagElement.TAG_SINCE:
						since.add(tag);
						break;
					case TagElement.TAG_VERSION:
						versions.add(tag);
						break;
					case TagElement.TAG_AUTHOR:
						authors.add(tag);
						break;
					case TagElement.TAG_SEE:
						sees.add(tag);
						break;
					case TagElement.TAG_DEPRECATED:
						if (deprecatedTag == null)
							deprecatedTag= tag; // the Javadoc tool only shows the first deprecated tag
						break;
					case TagElement.TAG_API_NOTE:
						apinote.add(tag);
						break;
					case TagElement.TAG_IMPL_SPEC:
						implspec.add(tag);
						break;
					case TagElement.TAG_IMPL_NOTE:
						implnote.add(tag);
						break;
					case TagElement.TAG_HIDDEN:
						hidden.add(tag);
						break;
					default:
						rest.add(tag);
						break;
				}
			}
		}

		//TODO: @Documented annotations before header
		if (deprecatedTag != null)
			handleDeprecatedTag(deprecatedTag);
		if (start != null)
			handleContentElements(start.fragments());
		else if (fMethod != null) {
			CharSequence inherited= fJavadocLookup.getInheritedMainDescription(fMethod);
			// The Javadoc tool adds "Description copied from class: ..." (only for the main description).
			// We don't bother doing that.
			handleInherited(inherited);
		}

		CharSequence[] typeParameterDescriptions= new CharSequence[typeParameterNames.size()];
		boolean hasInheritedTypeParameters= inheritTypeParameterDescriptions(typeParameterNames, typeParameterDescriptions);
		boolean hasTypeParameters= typeParameters.size() > 0 || hasInheritedTypeParameters;

		CharSequence[] parameterDescriptions= new CharSequence[parameterNames.size()];
		boolean hasInheritedParameters= inheritParameterDescriptions(parameterNames, parameterDescriptions);
		boolean hasParameters= parameters.size() > 0 || hasInheritedParameters;

		CharSequence returnDescription= null;
		if (returnTag == null && needsReturnTag())
			returnDescription= fJavadocLookup.getInheritedReturnDescription(fMethod);
		boolean hasReturnTag= returnTag != null || returnDescription != null;

		CharSequence[] exceptionDescriptions= new CharSequence[exceptionNames.size()];
		boolean hasInheritedExceptions= inheritExceptionDescriptions(exceptionNames, exceptionDescriptions);
		boolean hasExceptions= exceptions.size() > 0 || hasInheritedExceptions;

		if (hasParameters || hasTypeParameters || hasReturnTag || hasExceptions
				|| versions.size() > 0 || authors.size() > 0 || since.size() > 0 || sees.size() > 0 ||
				apinote.size() > 0 || implnote.size() > 0 || implspec.size() > 0 || uses.size() > 0 ||
				provides.size() > 0 || hidden.size() > 0 || rest.size() > 0
				|| (fBuf.length() > 0 && (parameterDescriptions.length > 0 || exceptionDescriptions.length > 0))
				) {
			handleSuperMethodReferences();
			fBuf.append(BLOCK_TAG_START);
			handleParameterTags(typeParameters, typeParameterNames, typeParameterDescriptions, true);
			handleParameterTags(parameters, parameterNames, parameterDescriptions, false);
			handleReturnTag(returnTag, returnDescription);
			handleExceptionTags(exceptions, exceptionNames, exceptionDescriptions);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_since_section, since);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_version_section, versions);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_author_section, authors);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_see_section, sees);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_api_note, apinote);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_impl_spec, implspec);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_impl_note, implnote);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_uses, uses);
			handleBlockTags(JavaDocMessages.JavaDoc2HTMLTextReader_provides, provides);
			if (hidden.size() > 0) {
				handleBlockTagsHidden();
			}
			handleBlockTags(rest);
			fBuf.append(BLOCK_TAG_END);

		} else if (fBuf.length() > 0) {
			handleSuperMethodReferences();
		}
	}

	private void handleBlockTagsHidden() {
		String replaceAll= fBuf.toString().replaceAll(BLOCK_TAG_START, "<dl hidden>"); //$NON-NLS-1$
		replaceAll= replaceAll.replaceAll(BlOCK_TAG_TITLE_START, "<dt hidden>"); //$NON-NLS-1$
		replaceAll= replaceAll.replaceAll(BlOCK_TAG_ENTRY_START, "<dd hidden>"); //$NON-NLS-1$
		// For tags like deprecated
		replaceAll= replaceAll.replaceAll(PARAM_NAME_START, "<b hidden>"); //$NON-NLS-1$
		fBuf.setLength(0);
		fBuf.append(replaceAll);
	}

	private void handleDeprecatedTag(TagElement tag) {
		fBuf.append("<p><b>"); //$NON-NLS-1$
		fBuf.append(JavaDocMessages.JavaDoc2HTMLTextReader_deprecated_section);
		fBuf.append("</b> <i>"); //$NON-NLS-1$
		handleContentElements(tag.fragments());
		fBuf.append("</i><p>"); //$NON-NLS-1$ TODO: Why not </p>? See https://bugs.eclipse.org/bugs/show_bug.cgi?id=243318 .
	}

	private void handleSuperMethodReferences() {
		if (fMethod != null) {
			try {
				StringBuffer superMethodReferences= createSuperMethodReferences(fMethod);
				if (superMethodReferences != null)
					fBuf.append(superMethodReferences);
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
	}

	private List<String> initTypeParameterNames() {
		if (fMethod != null) {
			try {
				ArrayList<String> typeParameterNames= new ArrayList<>();
				for (ITypeParameter typeParameter : fMethod.getTypeParameters()) {
					typeParameterNames.add(typeParameter.getElementName());
				}
				return typeParameterNames;
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
		return Collections.emptyList();
	}

	private List<String> initParameterNames() {
		if (fMethod != null) {
			try {
				return new ArrayList<>(Arrays.asList(fMethod.getParameterNames()));
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
		return Collections.emptyList();
	}

	private List<String> initExceptionNames() {
		if (fMethod != null) {
			try {
				ArrayList<String> exceptionNames= new ArrayList<>();
				for (String exceptionType : fMethod.getExceptionTypes()) {
					exceptionNames.add(Signature.getSimpleName(Signature.toString(exceptionType)));
				}
				return exceptionNames;
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
		}
		return Collections.emptyList();
	}

	private boolean needsReturnTag() {
		if (fMethod == null)
			return false;
		try {
			return ! Signature.SIG_VOID.equals(fMethod.getReturnType());
		} catch (JavaModelException e) {
			JavaPlugin.log(e);
			return false;
		}
	}

	private boolean inheritTypeParameterDescriptions(List<String> typeParameterNames, CharSequence[] typeParameterDescriptions) {
		boolean hasInheritedTypeParameters= false;
		for (int i= 0; i < typeParameterNames.size(); i++) {
			String name= typeParameterNames.get(i);
			if (name != null) {
				typeParameterDescriptions[i]= fJavadocLookup.getInheritedTypeParamDescription(fMethod, i);
				if (typeParameterDescriptions[i] != null)
					hasInheritedTypeParameters= true;
			}
		}
		return hasInheritedTypeParameters;
	}

	private boolean inheritParameterDescriptions(List<String> parameterNames, CharSequence[] parameterDescriptions) {
		boolean hasInheritedParameters= false;
		for (int i= 0; i < parameterNames.size(); i++) {
			String name= parameterNames.get(i);
			if (name != null) {
				parameterDescriptions[i]= fJavadocLookup.getInheritedParamDescription(fMethod, i);
				if (parameterDescriptions[i] != null)
					hasInheritedParameters= true;
			}
		}
		return hasInheritedParameters;
	}

	private boolean inheritExceptionDescriptions(List<String> exceptionNames, CharSequence[] exceptionDescriptions) {
		boolean hasInheritedExceptions= false;
		for (int i= 0; i < exceptionNames.size(); i++) {
			String name= exceptionNames.get(i);
			if (name != null) {
				exceptionDescriptions[i]= fJavadocLookup.getInheritedExceptionDescription(fMethod, name);
				if (exceptionDescriptions[i] != null)
					hasInheritedExceptions= true;
			}
		}
		return hasInheritedExceptions;
	}

	CharSequence getMainDescription() {
		if (fMainDescription == null) {
			fMainDescription= new StringBuffer();
			fBuf= fMainDescription;
			fLiteralContent= 0;

			List<TagElement> tags= fJavadoc.tags();
			for (TagElement tag : tags) {
				String tagName= tag.getTagName();
				if (tagName == null) {
					handleContentElements(tag.fragments());
					break;
				}
			}

			fBuf= null;
		}
		return fMainDescription.length() > 0 ? fMainDescription : null;
	}

	CharSequence getReturnDescription() {
		if (fReturnDescription == null) {
			fReturnDescription= new StringBuffer();
			fBuf= fReturnDescription;
			fLiteralContent= 0;

			List<TagElement> tags= fJavadoc.tags();
			for (TagElement tag : tags) {
				String tagName= tag.getTagName();
				if (TagElement.TAG_RETURN.equals(tagName)) {
					handleContentElements(tag.fragments());
					break;
				}
			}

			fBuf= null;
		}
		return fReturnDescription.length() > 0 ? fReturnDescription : null;
	}

	CharSequence getInheritedTypeParamDescription(int typeParamIndex) {
		if (fMethod != null) {
			List<String> typeParameterNames= initTypeParameterNames();
			if (fTypeParamDescriptions == null) {
				fTypeParamDescriptions= new StringBuffer[typeParameterNames.size()];
			} else {
				StringBuffer description= fTypeParamDescriptions[typeParamIndex];
				if (description != null) {
					return description.length() > 0 ? description : null;
				}
			}

			StringBuffer description= new StringBuffer();
			fTypeParamDescriptions[typeParamIndex]= description;
			fBuf= description;
			fLiteralContent= 0;

			String typeParamName= typeParameterNames.get(typeParamIndex);
			List<TagElement> tags= fJavadoc.tags();
			for (TagElement tag : tags) {
				String tagName= tag.getTagName();
				if (TagElement.TAG_PARAM.equals(tagName)) {
					List<? extends ASTNode> fragments= tag.fragments();
					if (fragments.size() > 2) {
						Object first= fragments.get(0);
						Object second= fragments.get(1);
						Object third= fragments.get(2);
						if (first instanceof TextElement && second instanceof SimpleName && third instanceof TextElement) {
							String firstText= ((TextElement) first).getText();
							String thirdText= ((TextElement) third).getText();
							if ("<".equals(firstText) && ">".equals(thirdText)) { //$NON-NLS-1$ //$NON-NLS-2$
								String name= ((SimpleName) second).getIdentifier();
								if (name.equals(typeParamName)) {
									handleContentElements(fragments.subList(3, fragments.size()));
									break;
								}
							}
						}
					}
				}
			}

			fBuf= null;
			return description.length() > 0 ? description : null;
		}
		return null;
	}

	CharSequence getInheritedParamDescription(int paramIndex) throws JavaModelException {
		if (fMethod != null) {
			String[] parameterNames= fMethod.getParameterNames();
			if (fParamDescriptions == null) {
				fParamDescriptions= new StringBuffer[parameterNames.length];
			} else {
				StringBuffer description= fParamDescriptions[paramIndex];
				if (description != null) {
					return description.length() > 0 ? description : null;
				}
			}

			StringBuffer description= new StringBuffer();
			fParamDescriptions[paramIndex]= description;
			fBuf= description;
			fLiteralContent= 0;

			String paramName= parameterNames[paramIndex];
			List<TagElement> tags= fJavadoc.tags();
			for (TagElement tag : tags) {
				String tagName= tag.getTagName();
				if (TagElement.TAG_PARAM.equals(tagName)) {
					List<? extends ASTNode> fragments= tag.fragments();
					if (fragments.size() > 0) {
						Object first= fragments.get(0);
						if (first instanceof SimpleName) {
							String name= ((SimpleName) first).getIdentifier();
							if (name.equals(paramName)) {
								handleContentElements(fragments.subList(1, fragments.size()));
								break;
							}
						}
					}
				}
			}

			fBuf= null;
			return description.length() > 0 ? description : null;
		}
		return null;
	}

	CharSequence getExceptionDescription(String simpleName) {
		if (fMethod != null) {
			if (fExceptionDescriptions == null) {
				fExceptionDescriptions= new HashMap<>();
			} else {
				StringBuffer description= fExceptionDescriptions.get(simpleName);
				if (description != null) {
					return description.length() > 0 ? description : null;
				}
			}

			StringBuffer description= new StringBuffer();
			fExceptionDescriptions.put(simpleName, description);
			fBuf= description;
			fLiteralContent= 0;

			List<TagElement> tags= fJavadoc.tags();
			for (TagElement tag : tags) {
				String tagName= tag.getTagName();
				if (TagElement.TAG_THROWS.equals(tagName) || TagElement.TAG_EXCEPTION.equals(tagName)) {
					List<? extends ASTNode> fragments= tag.fragments();
					if (fragments.size() > 0) {
						Object first= fragments.get(0);
						if (first instanceof Name) {
							String name= ASTNodes.getSimpleNameIdentifier((Name) first);
							if (name.equals(simpleName)) {
								if (fragments.size() > 1)
									handleContentElements(fragments.subList(1, fragments.size()));
								break;
							}
						}
					}
				}
			}

			fBuf= null;
			return description.length() > 0 ? description : null;
		}
		return null;
	}


	private void handleContentElements(List<? extends ASTNode> nodes) {
		handleContentElements(nodes, false);
	}

	private void handleContentElements(List<? extends ASTNode> nodes, boolean skipLeadingWhitespace) {
		ASTNode previousNode= null;
		for (ASTNode child : nodes) {
			if (previousNode != null) {
				int previousEnd= previousNode.getStartPosition() + previousNode.getLength();
				int childStart= child.getStartPosition();
				if (previousEnd > childStart) {
					// should never happen, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=304826
					Exception exception= new Exception("Illegal ASTNode positions: previousEnd=" + previousEnd //$NON-NLS-1$
						+ ", childStart=" + childStart //$NON-NLS-1$
						+ ", element=" + fElement.getHandleIdentifier() //$NON-NLS-1$
						+ ", Javadoc:\n" + fSource); //$NON-NLS-1$
					JavaPlugin.log(exception);
				} else if (previousEnd != childStart) {
					// Need to preserve whitespace before a node that's not
					// directly following the previous node (e.g. on a new line)
					// due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=206518 :
					String textWithStars= fSource.substring(previousEnd, childStart);
					String text= removeDocLineIntros(textWithStars);
					fBuf.append(text);
				}
			}
			previousNode= child;
			if (child instanceof TextElement) {
				String text= ((TextElement) child).getText();
				if (skipLeadingWhitespace) {
					text= text.replaceFirst("^\\s", ""); //$NON-NLS-1$ //$NON-NLS-2$
				}
				// workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=233481 :
				text= text.replaceAll("(\r\n?|\n)([ \t]*\\*)", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
				handleText(text);
			} else if (child instanceof TagElement) {
				handleInlineTagElement((TagElement) child);
			} else {
				// This is unexpected. Fail gracefully by just copying the source.
				int start= child.getStartPosition();
				String text= fSource.substring(start, start + child.getLength());
				fBuf.append(removeDocLineIntros(text));
			}
		}
	}

	private String removeDocLineIntros(String textWithStars) {
		String lineBreakGroup= "(\\r\\n?|\\n)"; //$NON-NLS-1$
		String noBreakSpace= "[^\r\n&&\\s]"; //$NON-NLS-1$
		return textWithStars.replaceAll(lineBreakGroup + noBreakSpace + "*\\*" /*+ noBreakSpace + '?'*/, "$1"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private void handleText(String text) {
		if (fLiteralContent == 0) {
			fBuf.append(text);
		} else {
			appendEscaped(fBuf, text);
		}
	}

	private static void appendEscaped(StringBuffer buf, String text) {
		int nextToCopy= 0;
		int length= text.length();
		for (int i= 0; i < length; i++) {
			char ch= text.charAt(i);
			String rep= null;
			switch (ch) {
				case '&':
					rep= "&amp;"; //$NON-NLS-1$
					break;
				case '"':
					rep= "&quot;"; //$NON-NLS-1$
					break;
				case '<':
					rep= "&lt;"; //$NON-NLS-1$
					break;
				case '>':
					rep= "&gt;"; //$NON-NLS-1$
					break;
			}
			if (rep != null) {
				if (nextToCopy < i)
					buf.append(text.substring(nextToCopy, i));
				buf.append(rep);
				nextToCopy= i + 1;
			}
		}
		if (nextToCopy < length)
			buf.append(text.substring(nextToCopy));
	}

	private void handleInlineTagElement(TagElement node) {
		String name= node.getTagName();
		if (TagElement.TAG_VALUE.equals(name) && handleValueTag(node))
			return;

		boolean isLink= TagElement.TAG_LINK.equals(name);
		boolean isLinkplain= TagElement.TAG_LINKPLAIN.equals(name);
		boolean isCode= TagElement.TAG_CODE.equals(name);
		boolean isLiteral= TagElement.TAG_LITERAL.equals(name);
		boolean isSummary = TagElement.TAG_SUMMARY.equals(name);
		boolean isIndex = TagElement.TAG_INDEX.equals(name);
		boolean isSnippet = TagElement.TAG_SNIPPET.equals(name);

		if (isLiteral || isCode || isSummary || isIndex)
			fLiteralContent++;
		if (isLink || isCode)
			fBuf.append("<code>"); //$NON-NLS-1$

		if (isLink || isLinkplain)
			handleLink(node.fragments());
		else if (isSummary)
			handleSummary(node.fragments());
		else if (isIndex)
			handleIndex(node.fragments());
		else if (isCode || isLiteral)
			handleContentElements(node.fragments(), true);
		else if (isSnippet) {
			handleSnippet(node.fragments());
		}
		else if (handleInheritDoc(node) || handleDocRoot(node)) {
			// Handled
		} else {
			//print uninterpreted source {@tagname ...} for unknown tags
			int start= node.getStartPosition();
			String text= fSource.substring(start, start + node.getLength());
			fBuf.append(removeDocLineIntros(text));
		}

		if (isLink || isCode)
			fBuf.append("</code>"); //$NON-NLS-1$
		if (isSnippet)
			fBuf.append("</code></pre>"); //$NON-NLS-1$
		if (isLiteral || isCode)
			fLiteralContent--;

	}

	private boolean handleValueTag(TagElement node) {

		List<? extends ASTNode> fragments= node.fragments();
		try {
			if (!(fElement instanceof IMember)) {
				return false;
			}
			if (fragments.isEmpty()) {
				if (fElement instanceof IField && JdtFlags.isStatic((IField) fElement) && JdtFlags.isFinal((IField) fElement)) {
					IField field= (IField) fElement;
					return handleConstantValue(field, false);
				}
			} else if (fragments.size() == 1) {
				Object first= fragments.get(0);
				if (first instanceof MemberRef) {
					MemberRef memberRef= (MemberRef) first;
					IType type= fElement instanceof IType ? (IType) fElement : ((IMember) fElement).getDeclaringType();
					if (memberRef.getQualifier() != null) {
						String[][] qualifierTypes= type.resolveType(memberRef.getQualifier().getFullyQualifiedName());
						if (qualifierTypes != null && qualifierTypes.length == 1) {
							type= type.getJavaProject().findType(String.join(".", qualifierTypes[0]), (IProgressMonitor)null); //$NON-NLS-1$
						}
					}
					SimpleName name= memberRef.getName();
					while (type != null) {
						IField field= type.getField(name.getIdentifier());
						if (field != null && field.exists()) {
							if (JdtFlags.isStatic(field) && JdtFlags.isFinal(field))
								return handleConstantValue(field, true);
							break;
						}
						type= type.getDeclaringType();
					}
				}
			}
		} catch (JavaModelException e) {
			JavaPlugin.log(e);
		}

		return false;
	}

	private boolean handleConstantValue(IField field, boolean link) throws JavaModelException {
		String text= null;

		ISourceRange nameRange= field.getNameRange();
		if (SourceRange.isAvailable(nameRange)) {
			CompilationUnit cuNode= SharedASTProviderCore.getAST(field.getTypeRoot(), SharedASTProviderCore.WAIT_ACTIVE_ONLY, null);
			if (cuNode != null) {
				ASTNode nameNode= NodeFinder.perform(cuNode, nameRange);
				if (nameNode instanceof SimpleName) {
					IBinding binding= ((SimpleName) nameNode).resolveBinding();
					if (binding instanceof IVariableBinding) {
						IVariableBinding variableBinding= (IVariableBinding) binding;
						Object constantValue= variableBinding.getConstantValue();
						if (constantValue != null) {
							if (constantValue instanceof String) {
								text= ASTNodes.getEscapedStringLiteral((String) constantValue);
							} else {
								text= constantValue.toString(); // Javadoc tool is even worse for chars...
							}
						}
					}
				}
			}
		}

		if (text == null) {
			Object constant= field.getConstant();
			if (constant != null) {
				text= constant.toString();
			}
		}

		if (text != null) {
			text= HTMLPrinter.convertToHTMLContentWithWhitespace(text);
			if (link) {
				String uri;
				try {
					uri= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, field);
					fBuf.append(JavaElementLinks.createLink(uri, text));
				} catch (URISyntaxException e) {
					JavaPlugin.log(e);
					return false;
				}
			} else {
				handleText(text);
			}
			return true;
		}
		return false;
	}

	private boolean handleDocRoot(TagElement node) {
		if (!TagElement.TAG_DOCROOT.equals(node.getTagName()))
			return false;

		try {
			String url= null;
			if (fElement instanceof IMember && ((IMember) fElement).isBinary()) {
				URL javadocBaseLocation= JavaUI.getJavadocBaseLocation(fElement);
				if (javadocBaseLocation != null) {
					url= javadocBaseLocation.toExternalForm();
				}
			} else {
				IPackageFragmentRoot srcRoot= JavaModelUtil.getPackageFragmentRoot(fElement);
				if (srcRoot != null) {
					IResource resource= srcRoot.getResource();
					if (resource != null) {
						/*
						 * Too bad: Browser widget knows nothing about EFS and custom URL handlers,
						 * so IResource#getLocationURI() does not work in all cases.
						 * We only support the local file system for now.
						 * A solution could be https://bugs.eclipse.org/bugs/show_bug.cgi?id=149022 .
						 */
						IPath location= resource.getLocation();
						if (location != null) {
							url= location.toFile().toURI().toASCIIString();
						}
					}

				}
			}
			if (url != null) {
				if (url.endsWith("/")) { //$NON-NLS-1$
					url= url.substring(0, url.length() -1);
				}
				fBuf.append(url);
				return true;
			}
		} catch (JavaModelException e) {
		}
		return false;
	}


	/**
	 * Handle {&#64;inheritDoc}.
	 *
	 * @param node the node
	 * @return <code>true</code> iff the node was an {&#64;inheritDoc} node and has been handled
	 */
	private boolean handleInheritDoc(TagElement node) {
		if (! TagElement.TAG_INHERITDOC.equals(node.getTagName()))
			return false;
		try {
			if (fMethod == null)
				return false;

			TagElement blockTag= (TagElement) node.getParent();
			String blockTagName= blockTag.getTagName();

			if (blockTagName == null) {
				CharSequence inherited= fJavadocLookup.getInheritedMainDescription(fMethod);
				return handleInherited(inherited);

			} else if (TagElement.TAG_PARAM.equals(blockTagName)) {
				List<? extends ASTNode> fragments= blockTag.fragments();
				int size= fragments.size();
				if (size > 0) {
					Object first= fragments.get(0);
					if (first instanceof SimpleName) {
						String name= ((SimpleName) first).getIdentifier();
						String[] parameterNames= fMethod.getParameterNames();
						for (int i= 0; i < parameterNames.length; i++) {
							if (name.equals(parameterNames[i])) {
								CharSequence inherited= fJavadocLookup.getInheritedParamDescription(fMethod, i);
								return handleInherited(inherited);
							}
						}
					} else if (size > 2 && first instanceof TextElement) {
						String firstText= ((TextElement) first).getText();
						if ("<".equals(firstText)) { //$NON-NLS-1$
							Object second= fragments.get(1);
							Object third= fragments.get(2);
							if (second instanceof SimpleName && third instanceof TextElement) {
								String thirdText= ((TextElement) third).getText();
								if (">".equals(thirdText)) { //$NON-NLS-1$
									String name= ((SimpleName) second).getIdentifier();
									ITypeParameter[] typeParameters= fMethod.getTypeParameters();
									for (int i= 0; i < typeParameters.length; i++) {
										ITypeParameter typeParameter= typeParameters[i];
										if (name.equals(typeParameter.getElementName())) {
											CharSequence inherited= fJavadocLookup.getInheritedTypeParamDescription(fMethod, i);
											return handleInherited(inherited);
										}
									}
								}
							}
						}
					}
				}

			} else if (TagElement.TAG_RETURN.equals(blockTagName)) {
				CharSequence inherited= fJavadocLookup.getInheritedReturnDescription(fMethod);
				return handleInherited(inherited);

			} else if (TagElement.TAG_THROWS.equals(blockTagName) || TagElement.TAG_EXCEPTION.equals(blockTagName)) {
				List<? extends ASTNode> fragments= blockTag.fragments();
				if (fragments.size() > 0) {
					Object first= fragments.get(0);
					if (first instanceof Name) {
						String name= ASTNodes.getSimpleNameIdentifier((Name) first);
						CharSequence inherited= fJavadocLookup.getInheritedExceptionDescription(fMethod, name);
						return handleInherited(inherited);
					}
				}
			}
		} catch (JavaModelException e) {
			JavaPlugin.log(e);
		}
		return false;
	}

	private boolean handleInherited(CharSequence inherited) {
		if (inherited == null)
			return false;

		fBuf.append(inherited);
		return true;
	}

	private void handleBlockTags(String title, List<TagElement> tags) {
		if (tags.isEmpty())
			return;

		handleBlockTagTitle(title);

		for (TagElement tag : tags) {
			fBuf.append(BlOCK_TAG_ENTRY_START);
			if (TagElement.TAG_SEE.equals(tag.getTagName())) {
				handleSeeTag(tag);
			} else {
				handleContentElements(tag.fragments());
			}
			fBuf.append(BlOCK_TAG_ENTRY_END);
		}
	}

	private void handleReturnTag(TagElement tag, CharSequence returnDescription) {
		if (tag == null && returnDescription == null)
			return;

		handleBlockTagTitle(JavaDocMessages.JavaDoc2HTMLTextReader_returns_section);
		fBuf.append(BlOCK_TAG_ENTRY_START);
		if (tag != null)
			handleContentElements(tag.fragments());
		else
			fBuf.append(returnDescription);
		fBuf.append(BlOCK_TAG_ENTRY_END);
	}

	private void handleBlockTags(List<TagElement> tags) {
		for (TagElement tag : tags) {
			handleBlockTagTitle(tag.getTagName());
			fBuf.append(BlOCK_TAG_ENTRY_START);
			handleContentElements(tag.fragments());
			fBuf.append(BlOCK_TAG_ENTRY_END);
		}
	}

	private void handleBlockTagTitle(String title) {
		fBuf.append(BlOCK_TAG_TITLE_START);
		fBuf.append(title);
		fBuf.append(BlOCK_TAG_TITLE_END);
	}

	private void handleSeeTag(TagElement tag) {
		handleLink(tag.fragments());
	}

	private void handleExceptionTags(List<TagElement> tags, List<String> exceptionNames, CharSequence[] exceptionDescriptions) {
		if (tags.isEmpty() && containsOnlyNull(exceptionNames))
			return;

		handleBlockTagTitle(JavaDocMessages.JavaDoc2HTMLTextReader_throws_section);

		for (TagElement tag : tags) {
			fBuf.append(BlOCK_TAG_ENTRY_START);
			handleThrowsTag(tag);
			fBuf.append(BlOCK_TAG_ENTRY_END);
		}
		for (int i= 0; i < exceptionDescriptions.length; i++) {
			CharSequence description= exceptionDescriptions[i];
			String name= exceptionNames.get(i);
			if (name != null) {
				fBuf.append(BlOCK_TAG_ENTRY_START);
				handleLink(Collections.singletonList(fJavadoc.getAST().newSimpleName(name)));
				if (description != null) {
					fBuf.append(JavaElementLabels.CONCAT_STRING);
					fBuf.append(description);
				}
				fBuf.append(BlOCK_TAG_ENTRY_END);
			}
		}
	}

	private void handleThrowsTag(TagElement tag) {
		List<? extends ASTNode> fragments= tag.fragments();
		int size= fragments.size();
		if (size > 0) {
			handleLink(fragments.subList(0, 1));
			if (size > 1) {
				fBuf.append(JavaElementLabels.CONCAT_STRING);
				handleContentElements(fragments.subList(1, size));
			}
		}
	}

	private void handleParameterTags(List<TagElement> tags, List<String> parameterNames, CharSequence[] parameterDescriptions, boolean isTypeParameters) {
		if (tags.isEmpty() && containsOnlyNull(parameterNames))
			return;

		String tagTitle= isTypeParameters ? JavaDocMessages.JavaDoc2HTMLTextReader_type_parameters_section : JavaDocMessages.JavaDoc2HTMLTextReader_parameters_section;
		handleBlockTagTitle(tagTitle);

		for (TagElement tag : tags) {
			fBuf.append(BlOCK_TAG_ENTRY_START);
			handleParamTag(tag);
			fBuf.append(BlOCK_TAG_ENTRY_END);
		}
		for (int i= 0; i < parameterDescriptions.length; i++) {
			CharSequence description= parameterDescriptions[i];
			String name= parameterNames.get(i);
			if (name != null) {
				fBuf.append(BlOCK_TAG_ENTRY_START);
				fBuf.append(PARAM_NAME_START);
				if (isTypeParameters) {
					fBuf.append("&lt;"); //$NON-NLS-1$
				}
				fBuf.append(name);
				if (isTypeParameters) {
					fBuf.append("&gt;"); //$NON-NLS-1$
				}
				fBuf.append(PARAM_NAME_END);
				if (description != null)
					fBuf.append(description);
				fBuf.append(BlOCK_TAG_ENTRY_END);
			}
		}
	}

	private void handleParamTag(TagElement tag) {
		List<? extends ASTNode> fragments= tag.fragments();
		int i= 0;
		int size= fragments.size();
		if (size > 0) {
			Object first= fragments.get(0);
			fBuf.append(PARAM_NAME_START);
			if (first instanceof SimpleName) {
				String name= ((SimpleName) first).getIdentifier();
				fBuf.append(name);
				i++;
			} else if (first instanceof TextElement) {
				String firstText= ((TextElement) first).getText();
				if ("<".equals(firstText)) { //$NON-NLS-1$
					fBuf.append("&lt;"); //$NON-NLS-1$
					i++;
					if (size > 1) {
						Object second= fragments.get(1);
						if (second instanceof SimpleName) {
							String name= ((SimpleName) second).getIdentifier();
							fBuf.append(name);
							i++;
							if (size > 2) {
								Object third= fragments.get(2);
								String thirdText= ((TextElement) third).getText();
								if (">".equals(thirdText)) { //$NON-NLS-1$
									fBuf.append("&gt;"); //$NON-NLS-1$
									i++;
								}
							}
						}
					}
				}
			}
			fBuf.append(PARAM_NAME_END);

			handleContentElements(fragments.subList(i, fragments.size()));
		}
	}

	private void handleSummary(List<? extends ASTNode> fragments) {
		int fs= fragments.size();
		if (fs > 0) {
			Object first= fragments.get(0);
			if (first instanceof TextElement) {
				TextElement memberRef= (TextElement) first;
				fBuf.append(BlOCK_TAG_TITLE_START + "Summary: " + memberRef.getText() + BlOCK_TAG_TITLE_END); //$NON-NLS-1$
				return;
			}
		}
	}

	private void handleSnippet(List<? extends ASTNode> fragments) {
		int fs= fragments.size();
		if (fs > 0) {
			fBuf.append("<pre><code>"); //$NON-NLS-1$
			fBuf.append(BlOCK_TAG_ENTRY_START);
			for(ASTNode fragment : fragments) {
				if (fragment instanceof  TextElement) {
					TextElement memberRef= (TextElement) fragment;
					fBuf.append(memberRef.getText());
				} else if (fragment instanceof TagElement) {
					TagElement tagElem= (TagElement) fragment;
					String name= tagElem.getTagName();
					if (TagElement.TAG_HIGHLIGHT.equals(name)) {
						handleSnippetHighlight(tagElem.fragments(), tagElem.tagProperties());
					} else if (TagElement.TAG_REPLACE.equals(name)) {
						handleSnippetReplace(tagElem.fragments(), tagElem.tagProperties());
					}
				}
			}
			fBuf.append(BlOCK_TAG_ENTRY_END);
		}
	}

	private void handleSnippetReplace(List<? extends ASTNode> fragments, List<? extends ASTNode> tagProperties) {
		try {
			int fs= fragments.size();
			boolean process = arePropertyValuesStringLiterals(tagProperties) ? true : false;
			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
			String substitution = getPropertyValue("replacement", tagProperties); //$NON-NLS-1$
			Pattern regexPattern = null;
			if (regExValue != null) {
				regexPattern = Pattern.compile(regExValue);
			}
			if (fs > 0) {
				for(ASTNode fragment : fragments) {
					if (fragment instanceof  TextElement) {
						TextElement memberRef= (TextElement) fragment;
						String modifiedText = memberRef.getText();
						if (process) {
							if (regexPattern != null && process) {
								Matcher matcher = regexPattern.matcher(modifiedText);
								StringBuilder strBuild= new StringBuilder();
								int finalMatchIndex = 0;
								while (matcher.find()) {
									finalMatchIndex = matcher.end();
									matcher.appendReplacement(strBuild, substitution);
								}
								modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
							} else if (subStringValue != null) {
								int startIndex = 0;
								while (true) {
									startIndex = modifiedText.indexOf(subStringValue, startIndex);
									if (startIndex == -1) {
										break;
									} else {
										modifiedText = modifiedText.substring(0, startIndex) + substitution + modifiedText.substring(startIndex + subStringValue.length());
										startIndex = startIndex + substitution.length() ;
									}
								}
							} else {
								modifiedText = substitution;
							}
						}
						fBuf.append(modifiedText);
					}
				}
			}
		} catch (PatternSyntaxException e) {
			// do nothing
		}
	}

	private void handleSnippetHighlight(List<? extends ASTNode> fragments, List<? extends ASTNode> tagProperties) {
		try {
			int fs= fragments.size();
			String defHighlight= getHighlightHtmlTag(tagProperties);
			String startDefHighlight = '<' + defHighlight + '>';
			String endDefHighlight = "</" + defHighlight + '>'; //$NON-NLS-1$
			boolean process = true;
			if (defHighlight.length() == 0 || !arePropertyValuesStringLiterals(tagProperties)) {
				process = false;
			}
			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
			int additionalLength = startDefHighlight.length() + endDefHighlight.length();
			Pattern regexPattern = null;
			if (regExValue != null) {
				regexPattern = Pattern.compile(regExValue);
			}
			if (fs > 0) {
				for(ASTNode fragment : fragments) {
					if (fragment instanceof  TextElement) {
						TextElement memberRef= (TextElement) fragment;
						String modifiedText = memberRef.getText();
						if (process) {
							if (regexPattern != null && process) {
								Matcher matcher = regexPattern.matcher(modifiedText);
								StringBuilder strBuild= new StringBuilder();
								int finalMatchIndex = 0;
								while (matcher.find()) {
									finalMatchIndex = matcher.end();
									String replacementStr= startDefHighlight + modifiedText.substring(matcher.start(), matcher.end()) + endDefHighlight;
									matcher.appendReplacement(strBuild, replacementStr);
								}
								modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
							} else if (subStringValue != null) {
								int startIndex = 0;
								while (true) {
									startIndex = modifiedText.indexOf(subStringValue, startIndex);
									if (startIndex == -1) {
										break;
									} else {
										modifiedText = modifiedText.substring(0, startIndex) + startDefHighlight + subStringValue + endDefHighlight + modifiedText.substring(startIndex + subStringValue.length());
										startIndex = startIndex + subStringValue.length() + additionalLength;
									}
								}
							} else {
								modifiedText = startDefHighlight + modifiedText + endDefHighlight;
							}
						}
						fBuf.append(modifiedText);
					}
				}
			}
		} catch (PatternSyntaxException e) {
			// do nothing
		}
	}

	private String getHighlightHtmlTag(List<? extends ASTNode> tagProperties) {
		String defaultTag= "b"; //$NON-NLS-1$
		if (tagProperties != null) {
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
						String tagValue = stripQuotes(tagProp.getStringValue());
						switch (tagValue) {
							case "bold" :  //$NON-NLS-1$
								defaultTag= "b"; //$NON-NLS-1$
								break;
							case "italic" :  //$NON-NLS-1$
								defaultTag= "i"; //$NON-NLS-1$
								break;
							case "highlighted" :  //$NON-NLS-1$
								defaultTag= "mark"; //$NON-NLS-1$
								break;
							default :
								defaultTag= ""; //$NON-NLS-1$
								break;
						}
						break;
					}
				}
			}
		}
		return defaultTag;
	}

	private boolean arePropertyValuesStringLiterals(List<? extends ASTNode> tagProperties) {
		boolean val= true;
		if (tagProperties != null) {
			final String SUBSTRING = "substring"; //$NON-NLS-1$
			final String REGEX = "regex"; //$NON-NLS-1$
			final String TYPE = "type"; //$NON-NLS-1$
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					String propName = tagProp.getName();
					if (SUBSTRING.equals(propName)
							|| REGEX.equals(propName)
							|| TYPE.equals(propName)) {
						String value= tagProp.getStringValue();
						String changed= stripQuotes(value);
						if (changed.equals(value)) {
							val= false;
							break;
						}
					}
				}
			}
		}
		return val;
	}
	private String getPropertyValue(String property, List<? extends ASTNode> tagProperties) {
		String defaultTag= null;
		if (tagProperties != null && property!= null) {
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					if (property.equals(tagProp.getName())) {
						defaultTag= stripQuotes(tagProp.getStringValue());
						break;
					}
				}
			}
		}
		return defaultTag;
	}

	private String stripQuotes (String str) {
		String newStr = str;
		if (str != null && str.length() >= 2) {
			int length = str.length();
			if ((str.charAt(0) == '"' && str.charAt(length-1) == '"')
					|| (str.charAt(0) == '\'' && str.charAt(length-1) == '\'')) {
				newStr = str.substring(1, length-1);
			}
		}
		return newStr;
	}

	private void handleIndex(List<? extends ASTNode> fragments) {
		int fs= fragments.size();
		if (fs > 0) {
			Object first= fragments.get(0);
			if (first instanceof TextElement) {
				TextElement memberRef= (TextElement) first;
				fBuf.append(  memberRef.getText() );
				return;
			}
		}
	}

	private void handleLink(List<? extends ASTNode> fragments) {
		//TODO: Javadoc shortens type names to minimal length according to context
		int fs= fragments.size();
		if (fs > 0) {
			Object first= fragments.get(0);
			String refTypeName= null;
			String refMemberName= null;
			String[] refMethodParamTypes= null;
			String[] refMethodParamNames= null;
			if (first instanceof Name) {
				Name name = (Name) first;
				refTypeName= name.getFullyQualifiedName();
			} else if (first instanceof MemberRef) {
				MemberRef memberRef= (MemberRef) first;
				Name qualifier= memberRef.getQualifier();
				refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
				refMemberName= memberRef.getName().getIdentifier();
			} else if (first instanceof MethodRef) {
				MethodRef methodRef= (MethodRef) first;
				Name qualifier= methodRef.getQualifier();
				refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
				refMemberName= methodRef.getName().getIdentifier();
				List<MethodRefParameter> params= methodRef.parameters();
				int ps= params.size();
				refMethodParamTypes= new String[ps];
				refMethodParamNames= new String[ps];
				for (int i= 0; i < ps; i++) {
					MethodRefParameter param= params.get(i);
					refMethodParamTypes[i]= ASTNodes.asString(param.getType());
					SimpleName paramName= param.getName();
					if (paramName != null)
						refMethodParamNames[i]= paramName.getIdentifier();
				}
			}

			if (refTypeName != null) {
				fBuf.append("<a href='"); //$NON-NLS-1$
				try {
					String scheme= JavaElementLinks.JAVADOC_SCHEME;
					String uri= JavaElementLinks.createURI(scheme, fElement, refTypeName, refMemberName, refMethodParamTypes);
					fBuf.append(uri);
				} catch (URISyntaxException e) {
					JavaPlugin.log(e);
				}
				fBuf.append("'>"); //$NON-NLS-1$
				if (fs > 1 && ((fs != 2) || !isWhitespaceTextElement(fragments.get(1)))) {
					handleContentElements(fragments.subList(1, fs), true);
				} else {
					fBuf.append(refTypeName);
					if (refMemberName != null) {
						if (refTypeName.length() > 0) {
							fBuf.append('.');
						}
						fBuf.append(refMemberName);
						if (refMethodParamTypes != null) {
							fBuf.append('(');
							for (int i= 0; i < refMethodParamTypes.length; i++) {
								String pType= refMethodParamTypes[i];
								fBuf.append(pType);
								String pName= refMethodParamNames[i];
								if (pName != null) {
									fBuf.append(' ').append(pName);
								}
								if (i < refMethodParamTypes.length - 1) {
									fBuf.append(", "); //$NON-NLS-1$
								}
							}
							fBuf.append(')');
						}
					}
				}
				fBuf.append("</a>"); //$NON-NLS-1$
			} else {
				handleContentElements(fragments);
			}
		}
	}

	private static boolean isWhitespaceTextElement(Object fragment) {
		if (!(fragment instanceof TextElement))
			return false;

		TextElement textElement= (TextElement) fragment;
		return textElement.getText().trim().length() == 0;
	}

	private boolean containsOnlyNull(List<String> parameterNames) {
		for (String string : parameterNames) {
			if (string != null)
				return false;
		}
		return true;
	}

	/**
	 * @param content HTML content produced by <code>getHTMLContent(...)</code>
	 * @return the baseURL to use for the given content, or <code>null</code> if none
	 * @since 3.10
	 */
	public static String extractBaseURL(String content) {
		int introStart= content.indexOf(BASE_URL_COMMENT_INTRO);
		if (introStart != -1) {
			int introLength= BASE_URL_COMMENT_INTRO.length();
			int endIndex= content.indexOf('"', introStart + introLength);
			if (endIndex != -1) {
				return content.substring(introStart + introLength, endIndex);
			}
		}
		return null;
	}

	/**
	 * Returns the Javadoc for a PackageDeclaration.
	 *
	 * @param packageDeclaration the Java element whose Javadoc has to be retrieved
	 * @return the package documentation in HTML format or <code>null</code> if there is no
	 *         associated Javadoc
	 * @throws CoreException if the Java element does not exists or an exception occurs while
	 *             accessing the file containing the package Javadoc
	 * @since 3.9
	 */
	public static String getHTMLContent(IPackageDeclaration packageDeclaration) throws CoreException {
		IJavaElement element= packageDeclaration.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
		if (element instanceof IPackageFragment) {
			return getHTMLContent((IPackageFragment) element);
		}
		return null;
	}


	/**
	 * Returns the Javadoc for a package which could be present in package.html, package-info.java
	 * or from an attached Javadoc.
	 *
	 * @param packageFragment the package which is requesting for the document
	 * @return the document content in HTML format or <code>null</code> if there is no associated
	 *         Javadoc
	 * @throws CoreException if the Java element does not exists or an exception occurs while
	 *             accessing the file containing the package Javadoc
	 * @since 3.9
	 */
	public static String getHTMLContent(IPackageFragment packageFragment) throws CoreException {
		IPackageFragmentRoot root= (IPackageFragmentRoot) packageFragment.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);

		//1==> Handle the case when the documentation is present in package-info.java or package-info.class file
		ITypeRoot packageInfo;
		boolean isBinary= root.getKind() == IPackageFragmentRoot.K_BINARY;
		if (isBinary) {
			packageInfo= packageFragment.getClassFile(JavaModelUtil.PACKAGE_INFO_CLASS);
		} else {
			packageInfo= packageFragment.getCompilationUnit(JavaModelUtil.PACKAGE_INFO_JAVA);
		}
		if (packageInfo != null && packageInfo.exists()) {
			String cuSource= packageInfo.getSource();
			//the source can be null for some of the class files
			if (cuSource != null) {
				Javadoc packageJavadocNode= getPackageJavadocNode(packageFragment, cuSource);
				if (packageJavadocNode != null) {
					IJavaElement element;
					if (isBinary) {
						element= ((IOrdinaryClassFile) packageInfo).getType();
					} else {
						element= packageInfo.getParent(); // parent is the IPackageFragment
					}
					return new JavadocContentAccess2(element, packageJavadocNode, cuSource).toHTML();
				}
			}
		}

		// 2==> Handle the case when the documentation is done in package.html file. The file can be either in normal source folder or coming from a jar file
		else {
			Object[] nonJavaResources= packageFragment.getNonJavaResources();
			// 2.1 ==>If the package.html file is present in the source or directly in the binary jar
			for (Object nonJavaResource : nonJavaResources) {
				if (nonJavaResource instanceof IFile) {
					IFile iFile= (IFile) nonJavaResource;
					if (iFile.exists() && JavaModelUtil.PACKAGE_HTML.equals(iFile.getName())) {
						return getIFileContent(iFile);
					}
				}
			}

			// 2.2==>The file is present in a binary container
			if (isBinary) {
				for (Object nonJavaResource : nonJavaResources) {
					// The content is from an external binary class folder
					if (nonJavaResource instanceof IJarEntryResource) {
						IJarEntryResource jarEntryResource= (IJarEntryResource) nonJavaResource;
						String encoding= getSourceAttachmentEncoding(root);
						if (JavaModelUtil.PACKAGE_HTML.equals(jarEntryResource.getName()) && jarEntryResource.isFile()) {
							return getHTMLContent(jarEntryResource, encoding);
						}
					}
				}
				//2.3 ==>The file is present in the source attachment path.
				String contents= getHTMLContentFromAttachedSource(root, packageFragment);
				if (contents != null)
					return contents;
			}
		}

		//3==> Handle the case when the documentation is coming from the attached Javadoc
		if ((root.isArchive() || root.isExternal())) {
			return packageFragment.getAttachedJavadoc(null);

		}

		return null;
	}

	private static String getHTMLContent(IJarEntryResource jarEntryResource, String encoding) throws CoreException {
		InputStream in= jarEntryResource.getContents();
		try {
			return getContentsFromInputStream(in, encoding);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					//ignore
				}
			}
		}
	}

	private static String getHTMLContentFromAttachedSource(IPackageFragmentRoot root, IPackageFragment packageFragment) throws CoreException {
		String filePath= packageFragment.getElementName().replace('.', '/') + '/' + JavaModelUtil.PACKAGE_INFO_JAVA;
		String contents= getFileContentFromAttachedSource(root, filePath);
		if (contents != null) {
			Javadoc packageJavadocNode= getPackageJavadocNode(packageFragment, contents);
			if (packageJavadocNode != null)
				return new JavadocContentAccess2(packageFragment, packageJavadocNode, contents).toHTML();

		}
		filePath= packageFragment.getElementName().replace('.', '/') + '/' + JavaModelUtil.PACKAGE_HTML;
		return getFileContentFromAttachedSource(root, filePath);
	}

	@SuppressWarnings("resource")
	private static String getFileContentFromAttachedSource(IPackageFragmentRoot root, String filePath) throws CoreException {
		IPath sourceAttachmentPath= root.getSourceAttachmentPath();
		if (sourceAttachmentPath != null) {
			File file= null ;
			String encoding= null;

			if (sourceAttachmentPath.getDevice() == null) {
				//the path could be a workspace relative path to a zip or to the source folder
				IWorkspaceRoot wsRoot= ResourcesPlugin.getWorkspace().getRoot();
				IResource res= wsRoot.findMember(sourceAttachmentPath);

				if (res instanceof IFile) {
					// zip in the workspace
					IPath location= res.getLocation();
					if (location == null)
						return null;
					file= location.toFile();
					encoding= ((IFile) res).getCharset(false);

				} else if (res instanceof IContainer) {
					// folder in the workspace
					res= ((IContainer) res).findMember(filePath);
					if (!(res instanceof IFile))
						return null;
					encoding= ((IFile) res).getCharset(false);
					if (encoding == null)
						encoding= getSourceAttachmentEncoding(root);
					return getContentsFromInputStream(((IFile) res).getContents(), encoding);
				}
			}

			if (file == null || !file.exists())
				file= sourceAttachmentPath.toFile();

			if (file.isDirectory()) {
				//the path is an absolute filesystem path to the source folder
				IPath packagedocPath= sourceAttachmentPath.append(filePath);
				if (packagedocPath.toFile().exists())
					return getFileContent(packagedocPath.toFile());

			} else if (file.exists()) {
				//the package documentation is in a Jar/Zip
				IPath sourceAttachmentRootPath= root.getSourceAttachmentRootPath();
				String packagedocPath;
				//consider the root path also in the search path if it exists
				if (sourceAttachmentRootPath != null) {
					packagedocPath= sourceAttachmentRootPath.append(filePath).toString();
				} else {
					packagedocPath= filePath;
				}
				ZipFile zipFile= null;
				InputStream in= null;
				try {
					zipFile= new ZipFile(file, ZipFile.OPEN_READ);
					ZipEntry packagedocFile= zipFile.getEntry(packagedocPath);
					if (packagedocFile != null) {
						in= zipFile.getInputStream(packagedocFile);
						if (encoding == null)
							encoding= getSourceAttachmentEncoding(root);
						return getContentsFromInputStream(in, encoding);
					}
				} catch (IOException e) {
					throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), e.getMessage(), e));
				} finally {
					try {
						if (in != null) {
							in.close();
						}
					} catch (IOException e) {
						//ignore
					}
					try {
						if (zipFile != null) {
							zipFile.close();//this will close the InputStream also
						}
					} catch (IOException e) {
						//ignore
					}
				}
			}
		}

		return null;
	}


	private static String getContentsFromInputStream(InputStream in, String encoding) throws CoreException {
		final int defaultFileSize= 15 * 1024;
		StringBuilder buffer= new StringBuilder(defaultFileSize);
		Reader reader= null;

		try {
			reader= new BufferedReader(new InputStreamReader(in, encoding), defaultFileSize);

			char[] readBuffer= new char[2048];
			int charCount= reader.read(readBuffer);

			while (charCount > 0) {
				buffer.append(readBuffer, 0, charCount);
				charCount= reader.read(readBuffer);
			}

		} catch (IOException e) {
			throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), e.getMessage(), e));
		} finally {
			try {
				if (reader != null) {
					reader.close();//this will also close the InputStream wrapped in the reader
				}
			} catch (IOException e) {
				//ignore
			}
		}
		return buffer.toString();
	}


	private static String getSourceAttachmentEncoding(IPackageFragmentRoot root) throws JavaModelException {
		String encoding= ResourcesPlugin.getEncoding();
		IClasspathEntry entry= root.getRawClasspathEntry();

		if (entry != null) {
			int kind= entry.getEntryKind();
			if (kind == IClasspathEntry.CPE_LIBRARY || kind == IClasspathEntry.CPE_VARIABLE) {
				for (IClasspathAttribute attrib : entry.getExtraAttributes()) {
					if (IClasspathAttribute.SOURCE_ATTACHMENT_ENCODING.equals(attrib.getName())) {
						return attrib.getValue();
					}
				}
			}
		}

		return encoding;
	}

	/**
	 * Reads the content of the IFile.
	 *
	 * @param file the file whose content has to be read
	 * @return the content of the file
	 * @throws CoreException if the file could not be successfully connected or disconnected
	 */
	private static String getIFileContent(IFile file) throws CoreException {
		String content= null;
		ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
		IPath fullPath= file.getFullPath();
		manager.connect(fullPath, LocationKind.IFILE, null);
		try {
			ITextFileBuffer buffer= manager.getTextFileBuffer(fullPath, LocationKind.IFILE);
			if (buffer != null) {
				content= buffer.getDocument().get();
			}
		} finally {
			manager.disconnect(fullPath, LocationKind.IFILE, null);
		}

		return content;
	}


	/**
	 * Reads the content of the java.io.File.
	 *
	 * @param file the file whose content has to be read
	 * @return the content of the file
	 * @throws CoreException if the file could not be successfully connected or disconnected
	 */
	private static String getFileContent(File file) throws CoreException {
		String content= null;
		ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();

		IPath fullPath= new Path(file.getAbsolutePath());
		manager.connect(fullPath, LocationKind.LOCATION, null);
		try {
			ITextFileBuffer buffer= manager.getTextFileBuffer(fullPath, LocationKind.LOCATION);
			if (buffer != null) {
				content= buffer.getDocument().get();
			}
		} finally {
			manager.disconnect(fullPath, LocationKind.LOCATION, null);
		}
		return content;
	}

}
