/*******************************************************************************
 * Copyright (c) 2002, 2015 GEBIT Gesellschaft fuer EDV-Beratung
 * und Informatik-Technologien mbH, 
 * Berlin, Duesseldorf, Frankfurt (Germany) 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:
 *     GEBIT Gesellschaft fuer EDV-Beratung und Informatik-Technologien mbH - initial API and implementation
 * 	   IBM Corporation - bug fixes
 *     John-Mason P. Shackelford (john-mason.shackelford@pearson.com) - bug 49383, 56299, 59024
 *     Brock Janiczak (brockj_eclipse@ihug.com.au ) - bug 78028, 78030 
 *     Remy Chi Jian Suen - bug 277587
 *******************************************************************************/

package org.eclipse.ant.internal.ui.editor;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.ExtensionPoint;
import org.apache.tools.ant.IntrospectionHelper;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.taskdefs.MacroDef;
import org.apache.tools.ant.taskdefs.MacroDef.Attribute;
import org.apache.tools.ant.taskdefs.MacroDef.TemplateElement;
import org.apache.tools.ant.taskdefs.MacroInstance;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Reference;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIImages;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.IAntUIConstants;
import org.eclipse.ant.internal.ui.dtd.IAttribute;
import org.eclipse.ant.internal.ui.dtd.IDfm;
import org.eclipse.ant.internal.ui.dtd.IElement;
import org.eclipse.ant.internal.ui.dtd.ISchema;
import org.eclipse.ant.internal.ui.dtd.ParseError;
import org.eclipse.ant.internal.ui.dtd.Parser;
import org.eclipse.ant.internal.ui.editor.TaskDescriptionProvider.ProposalNode;
import org.eclipse.ant.internal.ui.editor.templates.AntContext;
import org.eclipse.ant.internal.ui.editor.templates.AntTemplateAccess;
import org.eclipse.ant.internal.ui.editor.templates.AntTemplateInformationControlCreator;
import org.eclipse.ant.internal.ui.editor.templates.AntTemplateProposal;
import org.eclipse.ant.internal.ui.editor.templates.BuildFileContextType;
import org.eclipse.ant.internal.ui.editor.templates.TargetContextType;
import org.eclipse.ant.internal.ui.editor.templates.TaskContextType;
import org.eclipse.ant.internal.ui.model.AntDefiningTaskNode;
import org.eclipse.ant.internal.ui.model.AntElementNode;
import org.eclipse.ant.internal.ui.model.AntModel;
import org.eclipse.ant.internal.ui.model.AntProjectNode;
import org.eclipse.ant.internal.ui.model.AntTargetNode;
import org.eclipse.ant.internal.ui.model.AntTaskNode;
import org.eclipse.ant.internal.ui.model.IAntElement;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.bindings.TriggerSequence;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.contentassist.IContentAssistantExtension2;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.keys.IBindingService;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.ibm.icu.text.MessageFormat;

/**
 * The completion processor for the Ant Editor.
 */
public class AntEditorCompletionProcessor extends TemplateCompletionProcessor implements ICompletionListener {

	private Comparator<ICompletionProposal> proposalComparator = new Comparator<ICompletionProposal>() {
		@Override
		public int compare(ICompletionProposal o1, ICompletionProposal o2) {

			int type1 = getProposalType(o1);
			int type2 = getProposalType(o2);
			if (type1 != type2) {
				if (type1 > type2) {
					return 1;
				}
				return -1;
			}
			String string1 = o1.getDisplayString();
			String string2 = o2.getDisplayString();
			return string1.compareToIgnoreCase(string2);
		}

		private int getProposalType(Object o) {
			if (o instanceof AntCompletionProposal) {
				return ((AntCompletionProposal) o).getType();
			}
			return AntCompletionProposal.TASK_PROPOSAL;
		}
	};

	protected final static int PROPOSAL_MODE_NONE = 0;
	protected final static int PROPOSAL_MODE_BUILDFILE = 1;
	protected final static int PROPOSAL_MODE_TASK_PROPOSAL = 2;
	protected final static int PROPOSAL_MODE_PROPERTY_PROPOSAL = 3;
	protected final static int PROPOSAL_MODE_ATTRIBUTE_PROPOSAL = 4;
	protected final static int PROPOSAL_MODE_TASK_PROPOSAL_CLOSING = 5;
	protected final static int PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL = 6;
	protected final static int PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL = 7;

	private final static ICompletionProposal[] NO_PROPOSALS = new ICompletionProposal[0];

	/**
	 * The fully qualified name of the {@link MacroInstance} class
	 * 
	 * @since 3.5.500
	 */
	private static final String MACROINSTANCE_NAME = "org.apache.tools.ant.taskdefs.MacroInstance"; //$NON-NLS-1$

	/**
	 * The line where the cursor sits now.
	 * <P>
	 * The first line has index '1'.
	 */
	protected int lineNumber = -1;

	/**
	 * The startingColumn where the cursor sits now.
	 * <P>
	 * The first startingColumn has index '1'.
	 */
	protected int columnNumber = -1;

	/**
	 * The additional offset required from a required attribute to place the cursor for the current proposal
	 */
	private int additionalProposalOffset = -1;

	private static final String ANT_DTD_FILENAME = "/org/eclipse/ant/internal/ui/editor/ant1.6.2.dtd"; //$NON-NLS-1$

	/**
	 * The DTD.
	 */
	private static ISchema fgDtd;

	/**
	 * Cursor position, counted from the beginning of the document.
	 * <P>
	 * The first position has index '0'.
	 */
	protected int cursorPosition = -1;

	/**
	 * The text viewer.
	 */
	private ITextViewer viewer;

	/**
	 * The set of characters that will trigger the activation of the completion proposal computation.
	 */
	private char[] autoActivationChars = null;

	private String errorMessage;

	protected AntModel antModel;

	/**
	 * The proposal mode for the current content assist
	 * 
	 * @see #determineProposalMode(IDocument, int, String)
	 */
	private int currentProposalMode = -1;

	/**
	 * The prefix for the current content assist
	 */
	protected String currentPrefix = null;

	/**
	 * The current task string for content assist
	 * 
	 * @see #determineProposalMode(IDocument, int, String)
	 */
	protected String currentTaskString = null;

	private boolean fTemplatesOnly = false;
	protected IContentAssistantExtension2 fContentAssistant;

	public AntEditorCompletionProcessor(AntModel model) {
		super();
		antModel = model;
	}

	/**
	 * Parses the dtd.
	 */
	private ISchema parseDtd() throws ParseError, IOException {
		try (InputStream stream = getClass().getResourceAsStream(ANT_DTD_FILENAME); Reader reader = new InputStreamReader(stream, "UTF-8");) {//$NON-NLS-1$
			Parser parser = new Parser();
			ISchema schema = parser.parseDTD(reader, "project"); //$NON-NLS-1$
			return schema;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeCompletionProposals(org.eclipse.jface.text.ITextViewer, int)
	 */
	@Override
	public ICompletionProposal[] computeCompletionProposals(ITextViewer refViewer, int documentOffset) {
		this.viewer = refViewer;
		try {
			if (fTemplatesOnly) {
				fContentAssistant.setStatusMessage(getIterationGestureMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.0"))); //$NON-NLS-1$
				fContentAssistant.setEmptyMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.60")); //$NON-NLS-1$
				ICompletionProposal[] templates = determineTemplateProposals(refViewer, documentOffset);
				Arrays.sort(templates, proposalComparator);
				return templates;
			}
			fContentAssistant.setStatusMessage(getIterationGestureMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.61"))); //$NON-NLS-1$
			fContentAssistant.setEmptyMessage(AntEditorMessages.getString("AntEditorCompletionProcessor.62")); //$NON-NLS-1$
			ICompletionProposal[] matchingProposals = determineProposals();
			ICompletionProposal[] matchingTemplateProposals = determineTemplateProposals(refViewer, documentOffset);
			return mergeProposals(matchingProposals, matchingTemplateProposals);
		}
		finally {
			currentPrefix = null;
			currentProposalMode = -1;
			fTemplatesOnly = !fTemplatesOnly;
		}
	}

	protected ICompletionProposal[] determineTemplateProposals(ITextViewer refViewer, int documentOffset) {
		this.viewer = refViewer;
		String prefix = getCurrentPrefix();
		ICompletionProposal[] matchingTemplateProposals;
		if (prefix.length() == 0) {
			matchingTemplateProposals = determineTemplateProposalsForContext(documentOffset);
		} else {
			ICompletionProposal[] templateProposals = determineTemplateProposalsForContext(documentOffset);
			List<ICompletionProposal> templateProposalList = new ArrayList<>(templateProposals.length);
			for (int i = 0; i < templateProposals.length; i++) {
				if (templateProposals[i].getDisplayString().toLowerCase().startsWith(prefix)) {
					templateProposalList.add(templateProposals[i]);
				}
			}
			matchingTemplateProposals = templateProposalList.toArray(new ICompletionProposal[templateProposalList.size()]);
		}
		return matchingTemplateProposals;
	}

	// essentially a copy of super.computeCompletionProposals but we need to have both context types work
	// for target (task and target) context type in a backwards compatible way
	private ICompletionProposal[] determineTemplateProposalsForContext(int offset) {
		ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();

		// adjust offset to end of normalized selection
		int newoffset = offset;
		if (selection.getOffset() == newoffset) {
			newoffset = selection.getOffset() + selection.getLength();
		}

		String prefix = extractPrefix(viewer, newoffset);
		Region region = new Region(newoffset - prefix.length(), prefix.length());
		TemplateContext context = createContext(viewer, region);
		if (context == null) {
			return new ICompletionProposal[0];
		}

		context.setVariable("selection", selection.getText()); // name of the selection variables {line, word}_selection //$NON-NLS-1$

		Template[] templates;
		String contextTypeId = context.getContextType().getId();
		boolean isTargetContextType = contextTypeId.equals(TargetContextType.TARGET_CONTEXT_TYPE);
		if (isTargetContextType) {
			Template[] tasks = AntTemplateAccess.getDefault().getTemplateStore().getTemplates(TaskContextType.TASK_CONTEXT_TYPE);
			Template[] targets = getTemplates(contextTypeId);
			templates = new Template[tasks.length + targets.length];
			System.arraycopy(tasks, 0, templates, 0, tasks.length);
			System.arraycopy(targets, 0, templates, tasks.length, targets.length);
		} else {
			templates = getTemplates(contextTypeId);
		}

		List<ICompletionProposal> matches = new ArrayList<>();
		for (int i = 0; i < templates.length; i++) {
			Template template = templates[i];
			try {
				context.getContextType().validate(template.getPattern());
			}
			catch (TemplateException e) {
				continue;
			}
			if (template.matches(prefix, contextTypeId) || (isTargetContextType && template.matches(prefix, TaskContextType.TASK_CONTEXT_TYPE))) {
				matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
			}
		}

		Collections.sort(matches, proposalComparator);

		return matches.toArray(new ICompletionProposal[matches.size()]);
	}

	private ICompletionProposal[] mergeProposals(ICompletionProposal[] proposals1, ICompletionProposal[] proposals2) {

		ICompletionProposal[] combinedProposals = new ICompletionProposal[proposals1.length + proposals2.length];

		System.arraycopy(proposals1, 0, combinedProposals, 0, proposals1.length);
		System.arraycopy(proposals2, 0, combinedProposals, proposals1.length, proposals2.length);

		Arrays.sort(combinedProposals, proposalComparator);
		return combinedProposals;
	}

	/**
	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(ITextViewer, int)
	 */
	@Override
	public IContextInformation[] computeContextInformation(ITextViewer refViewer, int documentOffset) {
		return new IContextInformation[0];
	}

	/**
	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
	 */
	@Override
	public char[] getCompletionProposalAutoActivationCharacters() {
		return autoActivationChars;
	}

	/**
	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters()
	 */
	@Override
	public char[] getContextInformationAutoActivationCharacters() {
		return null;
	}

	/**
	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator()
	 */
	@Override
	public IContextInformationValidator getContextInformationValidator() {
		return null;
	}

	/**
	 * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage()
	 */
	@Override
	public String getErrorMessage() {
		return errorMessage;
	}

	/**
	 * Returns the new determined proposals.
	 */
	private ICompletionProposal[] determineProposals() {
		ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
		cursorPosition = selection.getOffset() + selection.getLength();

		IDocument doc = viewer.getDocument();
		try {
			lineNumber = doc.getLineOfOffset(cursorPosition);
			columnNumber = cursorPosition - doc.getLineOffset(lineNumber);
		}
		catch (BadLocationException e) {
			AntUIPlugin.log(e);
		}

		String prefix = getCurrentPrefix();
		if (prefix == null || cursorPosition == -1) {
			return NO_PROPOSALS;
		}

		ICompletionProposal[] proposals = getProposalsFromDocument(doc, prefix);
		currentTaskString = null;
		return proposals;
	}

	/**
	 * Returns the proposals for the specified document.
	 */
	protected ICompletionProposal[] getProposalsFromDocument(IDocument document, String prefix) {
		ICompletionProposal[] proposals = null;
		currentProposalMode = determineProposalMode(document, cursorPosition, prefix);
		switch (currentProposalMode) {
			case PROPOSAL_MODE_ATTRIBUTE_PROPOSAL:
				proposals = getAttributeProposals(currentTaskString, prefix);
				if (proposals.length == 0) {
					errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.28"); //$NON-NLS-1$
				}
				break;
			case PROPOSAL_MODE_TASK_PROPOSAL:
				String parentName = getParentName(document, lineNumber, columnNumber);
				if (parentName == null || parentName.length() == 0) { // outside of any parent element
					proposals = NO_PROPOSALS;
					currentProposalMode = PROPOSAL_MODE_NONE;
				} else {
					proposals = getTaskProposals(document, parentName, prefix);
				}
				if (proposals.length == 0) {
					errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.29"); //$NON-NLS-1$
				}
				break;
			case PROPOSAL_MODE_BUILDFILE:
				proposals = getBuildFileProposals(document, prefix);
				if (proposals.length == 0) {
					errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.29"); //$NON-NLS-1$
				}
				break;
			case PROPOSAL_MODE_TASK_PROPOSAL_CLOSING:
				ICompletionProposal proposal = getClosingTaskProposal(getOpenElementName(), prefix, true);
				if (proposal == null) {
					errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.30"); //$NON-NLS-1$
					proposals = NO_PROPOSALS;
				} else {
					proposals = new ICompletionProposal[] { proposal };
				}
				break;
			case PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL:
				String textToSearch = document.get().substring(0, cursorPosition - prefix.length());
				String attributeString = getAttributeStringFromDocumentStringToPrefix(textToSearch);
				if ("target".equalsIgnoreCase(currentTaskString) || "extension-point".equalsIgnoreCase(currentTaskString)) { //$NON-NLS-1$ //$NON-NLS-2$
					proposals = getTargetAttributeValueProposals(document, textToSearch, prefix, attributeString);
				} else if ("antcall".equalsIgnoreCase(currentTaskString)) { //$NON-NLS-1$
					proposals = getAntCallAttributeValueProposals(document, prefix, attributeString);
				} else if ("project".equalsIgnoreCase(currentTaskString)) { //$NON-NLS-1$
					proposals = getProjectAttributeValueProposals(prefix, attributeString);
				} else if ("refid".equalsIgnoreCase(attributeString) || "classpathref".equalsIgnoreCase(attributeString) //$NON-NLS-1$//$NON-NLS-2$
						|| "sourcepathref".equalsIgnoreCase(attributeString) || "bootpathref".equalsIgnoreCase(attributeString)) { //$NON-NLS-1$ //$NON-NLS-2$
					proposals = getReferencesValueProposals(prefix);
				} else {
					proposals = getAttributeValueProposals(currentTaskString, attributeString, prefix);
				}
				if (proposals.length == 0) {
					errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.31"); //$NON-NLS-1$
				}
				break;
			case PROPOSAL_MODE_PROPERTY_PROPOSAL:
				proposals = getPropertyProposals(document, prefix, cursorPosition);
				if (proposals.length == 0) {
					errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.32"); //$NON-NLS-1$
				}
				break;
			case PROPOSAL_MODE_NONE:
			default:
				proposals = NO_PROPOSALS;
				errorMessage = AntEditorMessages.getString("AntEditorCompletionProcessor.33"); //$NON-NLS-1$
		}

		if (proposals.length > 0) {
			errorMessage = IAntCoreConstants.EMPTY_STRING;
		}
		return proposals;

	}

	private ICompletionProposal[] getProjectAttributeValueProposals(String prefix, String attributeName) {
		if (attributeName.equalsIgnoreCase(IAntCoreConstants.DEFAULT)) {
			return getDefaultValueProposals(prefix);
		}

		return NO_PROPOSALS;
	}

	private ICompletionProposal[] getDefaultValueProposals(String prefix) {
		Map<String, Target> targets = getTargets();
		List<AntCompletionProposal> defaultProposals = new ArrayList<>(targets.size());
		Iterator<Target> itr = targets.values().iterator();
		Target target;
		String targetName;
		while (itr.hasNext()) {
			target = itr.next();
			targetName = target.getName();
			if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0) {
				defaultProposals.add(new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), getTargetImage(targetName), targetName, target.getDescription(), AntCompletionProposal.TASK_PROPOSAL));
			}
		}
		ICompletionProposal[] proposals = new ICompletionProposal[defaultProposals.size()];
		return defaultProposals.toArray(proposals);
	}

	private ICompletionProposal[] getReferencesValueProposals(String prefix) {
		Project project = antModel.getProjectNode().getProject();
		Map<String, Object> references = project.getReferences();
		if (references.isEmpty()) {
			return NO_PROPOSALS;
		}

		IAntElement node = antModel.getNode(cursorPosition, false);
		if (node == null) {
			return NO_PROPOSALS;
		}
		while (node.getParentNode() instanceof AntTaskNode) {
			node = node.getParentNode();
		}
		String id = null;
		if (node instanceof AntTaskNode) {
			id = ((AntTaskNode) node).getId();
		}
		Set<String> refIds = references.keySet();
		List<ICompletionProposal> proposals = new ArrayList<>(refIds.size());
		String refId;
		ICompletionProposal proposal;
		int prefixLength = prefix.length();
		int replacementOffset = cursorPosition - prefixLength;
		Iterator<String> iter = refIds.iterator();
		while (iter.hasNext()) {
			refId = iter.next();
			if (!refId.equals(id) && (prefixLength == 0 || refId.toLowerCase().startsWith(prefix))) {
				proposal = new AntCompletionProposal(refId, replacementOffset, prefixLength, refId.length(), null, refId, null, AntCompletionProposal.TASK_PROPOSAL);
				proposals.add(proposal);
			}
		}
		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	protected ICompletionProposal[] getTargetAttributeValueProposals(IDocument document, String textToSearch, String prefix, String attributeName) {
		if (attributeName.equalsIgnoreCase("depends")) { //$NON-NLS-1$
			return getDependsValueProposals(document, prefix);
		} else if (attributeName.equalsIgnoreCase("if") || attributeName.equalsIgnoreCase("unless")) { //$NON-NLS-1$ //$NON-NLS-2$
			if (!textToSearch.trim().endsWith(",")) { //$NON-NLS-1$
				return getPropertyProposals(document, prefix, cursorPosition);
			}
		} else if (attributeName.equalsIgnoreCase("extensionOf")) {//$NON-NLS-1$
			return getExtensionOfValueProposals(prefix);
		}

		return NO_PROPOSALS;
	}

	private ICompletionProposal[] getExtensionOfValueProposals(String prefix) {
		List<ICompletionProposal> extensions = new ArrayList<>();
		Map<String, Target> targets = getTargets();
		Set<String> targetNames = targets.keySet();
		for (String targetName : targetNames) {
			Target currentTarget = targets.get(targetName);
			if (currentTarget instanceof ExtensionPoint) {
				extensions.add(new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), getTargetImage(targetName), targetName, targets.get(targetName).getDescription(), AntCompletionProposal.TASK_PROPOSAL));
			}

		}
		return extensions.toArray(new ICompletionProposal[extensions.size()]);
	}

	protected ICompletionProposal[] getAntCallAttributeValueProposals(IDocument document, String prefix, String attributeName) {
		if (attributeName.equalsIgnoreCase("target")) { //$NON-NLS-1$
			return getTargetProposals(document, prefix);
		}

		return NO_PROPOSALS;
	}

	private ICompletionProposal[] getTargetProposals(IDocument document, String prefix) {
		String currentTargetName = getEnclosingTargetName(document, lineNumber, columnNumber);
		if (currentTargetName == null) {
			return NO_PROPOSALS;
		}

		Map<String, Target> targets = getTargets();
		Set<String> targetNames = targets.keySet();
		List<ICompletionProposal> proposals = new ArrayList<>(targets.size() - 2); // current target and implicit target
		for (String targetName : targetNames) {
			if (targetName.equals(currentTargetName)) {
				continue;
			}
			if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0) {
				proposals.add(new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), getTargetImage(targetName), targetName, targets.get(targetName).getDescription(), AntCompletionProposal.TASK_PROPOSAL));
			}
		}
		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	/**
	 * Retrieves the representative image of a target of the given name. If the target cannot be found, <code>null</code> will be returned.
	 * 
	 * @param targetName
	 *            the target's name
	 * @return an image suitable for representing the target, or <code>null</code> if the target cannot be found
	 * @since 3.6
	 */
	private Image getTargetImage(String targetName) {
		AntTargetNode targetNode = antModel.getTargetNode(targetName);
		if (targetNode == null) {
			return null;
		} else if (targetNode.isInternal()) {
			return AntUIImages.getImage(IAntUIConstants.IMG_ANT_TARGET_INTERNAL);
		} else if (targetNode.isDefaultTarget()) {
			return AntUIImages.getImage(IAntUIConstants.IMG_ANT_DEFAULT_TARGET);
		} else {
			return AntUIImages.getImage(IAntUIConstants.IMG_ANT_TARGET);
		}
	}

	private ICompletionProposal[] getDependsValueProposals(IDocument document, String prefix) {
		List<String> possibleDependencies = new ArrayList<>();
		String currentTargetName = getEnclosingTargetName(document, lineNumber, columnNumber);
		if (currentTargetName == null) {
			return NO_PROPOSALS;
		}

		Map<String, Target> targets = getTargets();
		Set<String> targetNames = targets.keySet();
		Enumeration<String> dependencies = null;
		for (String targetName : targetNames) {
			if (targetName.equals(currentTargetName)) {
				Target currentTarget = targets.get(targetName);
				dependencies = currentTarget.getDependencies();
				continue;
			}
			if (targetName.toLowerCase().startsWith(prefix) && targetName.length() > 0) {
				possibleDependencies.add(targetName);
			}
		}
		if (dependencies != null) {
			while (dependencies.hasMoreElements()) {
				possibleDependencies.remove(dependencies.nextElement());
			}
		}
		ArrayList<ICompletionProposal> proposals = new ArrayList<>(possibleDependencies.size());
		for (String targetName : possibleDependencies) {
			ICompletionProposal proposal = new AntCompletionProposal(targetName, cursorPosition - prefix.length(), prefix.length(), targetName.length(), getTargetImage(targetName), targetName, targets.get(targetName).getDescription(), AntCompletionProposal.TASK_PROPOSAL);
			proposals.add(proposal);
		}
		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	/**
	 * Returns all possible attributes for the specified task.
	 * 
	 * @param taskName
	 *            the name of the task for that the attribute shall be completed
	 * @param prefix
	 *            prefix, that all proposals should start with. The prefix may be an empty string.
	 */
	protected ICompletionProposal[] getAttributeProposals(String taskName, String prefix) {
		List<ICompletionProposal> proposals = new ArrayList<>();
		IElement element = getDtd().getElement(taskName);
		if (element != null) {
			Iterator<String> keys = element.getAttributes().keySet().iterator();
			while (keys.hasNext()) {
				String attrName = keys.next();
				if (prefix.length() == 0 || attrName.toLowerCase().startsWith(prefix)) {
					IAttribute dtdAttributes = element.getAttributes().get(attrName);
					String replacementString = attrName + "=\"\""; //$NON-NLS-1$
					String displayString = attrName;
					String[] items = dtdAttributes.getEnum();
					if (items != null) {
						if (items.length > 1) {
							displayString += " - ("; //$NON-NLS-1$
						}
						for (int i = 0; i < items.length; i++) {
							displayString += items[i];
							if (i + 1 < items.length) {
								displayString += " | "; //$NON-NLS-1$
							} else {
								displayString += ")"; //$NON-NLS-1$
							}
						}
					}

					addAttributeProposal(taskName, prefix, proposals, attrName, replacementString, displayString, true);
				}
			}
		} else { // possibly a user defined task or type
			AntTypeDefinition taskClass = getTaskClass(taskName);
			if (taskClass != null) {
				if (MACROINSTANCE_NAME.equals(taskClass.getClassName())) {
					addMacroDefAttributeProposals(taskName, prefix, proposals);
				} else {
					IntrospectionHelper helper = getIntrospectionHelper(taskClass);
					if (helper != null) {
						addAttributeProposals(helper, taskName, prefix, proposals);
					}
				}
			} else { // nested user defined element
				AntTypeDefinition nestedType = getNestedType();
				if (nestedType != null) {
					IntrospectionHelper helper = getIntrospectionHelper(nestedType);
					if (helper != null) {
						addAttributeProposals(helper, taskName, prefix, proposals);
					}
				}
			}
		}
		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	private void addAttributeProposals(IntrospectionHelper helper, String taskName, String prefix, List<ICompletionProposal> proposals) {
		Enumeration<String> attributes = helper.getAttributes();
		while (attributes.hasMoreElements()) {
			String attribute = attributes.nextElement();
			if (prefix.length() == 0 || attribute.toLowerCase().startsWith(prefix)) {
				String replacementString = attribute + "=\"\""; //$NON-NLS-1$
				addAttributeProposal(taskName, prefix, proposals, attribute, replacementString, attribute, false);
			}
		}
	}

	private AntTypeDefinition getNestedType() {
		AntElementNode currentNode = antModel.getNode(cursorPosition, false);
		if (currentNode == null) {
			return null;
		}
		IAntElement parent = currentNode.getParentNode();
		if (parent instanceof AntTaskNode) {
			String parentName = parent.getName();
			if (hasNestedElements(parentName)) {
				AntTypeDefinition taskClass = getTaskClass(parentName);
				if (taskClass != null) {
					IntrospectionHelper helper = getIntrospectionHelper(taskClass);
					if (helper != null) {
						try {
							Class<?> nestedType = helper.getElementType(currentNode.getName());
							// TODO probably a much better way to find the definition of a nested type than this
							AntTypeDefinition def = new AntTypeDefinition();
							def.setClass(nestedType);
							def.setClassName(nestedType.getName());
							return def;
						}
						catch (BuildException be) {
							// do nothing
						}
					}
				}
			}
		}
		return null;
	}

	private IntrospectionHelper getIntrospectionHelper(AntTypeDefinition taskClass) {
		Project p = antModel.getProjectNode().getProject();
		Class<?> clazz = taskClass.getExposedClass(p);
		if (clazz != null) {
			IntrospectionHelper helper = null;
			try {
				helper = IntrospectionHelper.getHelper(antModel.getProjectNode().getProject(), clazz);
			}
			catch (NoClassDefFoundError e) {
				// ignore as a task may require additional classpath components
			}
			return helper;
		}
		return null;
	}

	private void addMacroDefAttributeProposals(String taskName, String prefix, List<ICompletionProposal> proposals) {
		currentProposalMode = PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
		AntDefiningTaskNode node = antModel.getDefininingTaskNode(taskName);
		Object task = node.getRealTask();
		if (!(task instanceof MacroDef)) {
			return;
		}
		List<Attribute> attributes = ((MacroDef) task).getAttributes();
		Iterator<Attribute> itr = attributes.iterator();
		while (itr.hasNext()) {
			MacroDef.Attribute attribute = itr.next();
			String attributeName = attribute.getName();
			if (!(prefix.length() == 0 || attributeName.toLowerCase().startsWith(prefix))) {
				continue;
			}
			String replacementString = attributeName + "=\"\""; //$NON-NLS-1$
			String proposalInfo = null;

			String description = attribute.getDescription();
			if (description != null) {
				proposalInfo = description;
			}
			String deflt = attribute.getDefault();
			if (deflt != null && deflt.length() > 0) {
				proposalInfo = (proposalInfo == null ? "<BR><BR>" : (proposalInfo += "<BR><BR>")); //$NON-NLS-1$ //$NON-NLS-2$
				proposalInfo += MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.59"), new Object[] { deflt }); //$NON-NLS-1$
			}

			ICompletionProposal proposal = new AntCompletionProposal(replacementString, cursorPosition - prefix.length(), prefix.length(), attributeName.length() + 2, null, attributeName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
			proposals.add(proposal);
		}
	}

	private void addMacroDefElementProposals(String taskName, String prefix, List<ICompletionProposal> proposals) {
		AntDefiningTaskNode node = antModel.getDefininingTaskNode(taskName);
		Object task = node.getRealTask();
		if (!(task instanceof MacroDef)) {
			return;
		}
		Map<String, TemplateElement> elements = ((MacroDef) task).getElements();
		Iterator<String> itr = elements.keySet().iterator();
		int prefixLength = prefix.length();
		int replacementOffset = cursorPosition - prefixLength;
		while (itr.hasNext()) {
			String elementName = itr.next();
			if (!(prefixLength == 0 || elementName.toLowerCase().startsWith(prefix))) {
				continue;
			}
			MacroDef.TemplateElement element = elements.get(elementName);
			String replacementString = MessageFormat.format("<{0}>\n</{1}>", new Object[] { elementName, elementName }); //$NON-NLS-1$
			String proposalInfo = null;

			String description = element.getDescription();
			if (description != null) {
				proposalInfo = description;
			}
			proposalInfo = (proposalInfo == null ? "<BR><BR>" : (proposalInfo += "<BR><BR>")); //$NON-NLS-1$ //$NON-NLS-2$

			if (element.isOptional()) {
				proposalInfo += AntEditorMessages.getString("AntEditorCompletionProcessor.1"); //$NON-NLS-1$
			} else {
				proposalInfo += AntEditorMessages.getString("AntEditorCompletionProcessor.2"); //$NON-NLS-1$
			}

			ICompletionProposal proposal = new AntCompletionProposal(replacementString, replacementOffset, prefixLength, elementName.length() + 2, null, elementName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
			proposals.add(proposal);
		}
	}

	private void addAttributeProposal(String taskName, String prefix, List<ICompletionProposal> proposals, String attrName, String replacementString, String displayString, boolean lookupDescription) {

		String proposalInfo = null;
		if (lookupDescription) {
			String required = getDescriptionProvider().getRequiredAttributeForTaskAttribute(taskName, attrName);
			if (required != null && required.length() > 0) {
				proposalInfo = AntEditorMessages.getString("AntEditorCompletionProcessor.Required___4") + required; //$NON-NLS-1$
				proposalInfo += "<BR><BR>"; //$NON-NLS-1$
			}
			String description = getDescriptionProvider().getDescriptionForTaskAttribute(taskName, attrName);
			if (description != null) {
				proposalInfo = (proposalInfo == null ? IAntCoreConstants.EMPTY_STRING : proposalInfo);
				proposalInfo += description;
			}
		}

		ICompletionProposal proposal = new AntCompletionProposal(replacementString, cursorPosition - prefix.length(), prefix.length(), attrName.length() + 2, null, displayString, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
		proposals.add(proposal);
	}

	/**
	 * Returns all possible values for the specified attribute of the specified task.
	 * 
	 * @param aTaskName
	 *            the name of the task that the specified attribute belongs to.
	 * 
	 * @param anAttributeName
	 *            the name of the attribute for that the value shall be completed
	 * 
	 * @param prefix
	 *            the prefix that all proposals should start with. The prefix may be an empty string.
	 */
	private ICompletionProposal[] getAttributeValueProposals(String taskName, String attributeName, String prefix) {
		List<ICompletionProposal> proposals = new ArrayList<>();
		IElement taskElement = getDtd().getElement(taskName);
		if (taskElement != null) {
			IAttribute attribute = taskElement.getAttributes().get(attributeName);
			if (attribute != null) {
				String[] items = attribute.getEnum();
				if (items != null) {
					String item;
					for (int i = 0; i < items.length; i++) {
						item = items[i];
						if (prefix.length() == 0 || item.toLowerCase().startsWith(prefix)) {
							proposals.add(new AntCompletionProposal(item, cursorPosition - prefix.length(), prefix.length(), item.length(), null, item, null, AntCompletionProposal.TASK_PROPOSAL));
						}
					}
				}
			}
		} else { // possibly a user defined task or type
			AntTypeDefinition taskClass = getTaskClass(taskName);
			if (taskClass != null) {
				IntrospectionHelper helper = getIntrospectionHelper(taskClass);
				if (helper != null) {
					addAttributeValueProposals(helper, attributeName, prefix, proposals);
				}
			} else { // nested user defined element
				AntTypeDefinition nestedType = getNestedType();
				if (nestedType != null) {
					IntrospectionHelper helper = getIntrospectionHelper(nestedType);
					if (helper != null) {
						addAttributeValueProposals(helper, attributeName, prefix, proposals);
					}
				}
			}
		}
		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	private void addAttributeValueProposals(IntrospectionHelper helper, String attributeName, String prefix, List<ICompletionProposal> proposals) {
		Enumeration<String> attributes = helper.getAttributes();
		while (attributes.hasMoreElements()) {
			String attribute = attributes.nextElement();
			if (attribute.equals(attributeName)) {
				Class<?> attributeType = helper.getAttributeType(attribute);
				addAttributeValueProposalsForAttributeType(attributeType, prefix, proposals);
				break;
			}
		}
	}

	private void addAttributeValueProposalsForAttributeType(Class<?> attributeType, String prefix, List<ICompletionProposal> proposals) {
		if ((attributeType == Boolean.TYPE || attributeType == Boolean.class) && prefix.length() <= 5) {
			addBooleanAttributeValueProposals(prefix, proposals);
		} else if (EnumeratedAttribute.class.isAssignableFrom(attributeType)) {
			try {
				addEnumeratedAttributeValueProposals(attributeType, prefix, proposals);
			}
			catch (InstantiationException e) {
				// do nothing
			}
			catch (IllegalAccessException e) {
				// do nothing
			}
		} else if (Reference.class == attributeType) {
			proposals.addAll(Arrays.asList(getReferencesValueProposals(prefix)));
		}
	}

	private void addEnumeratedAttributeValueProposals(Class<?> type, String prefix, List<ICompletionProposal> proposals) throws InstantiationException, IllegalAccessException {
		EnumeratedAttribute ea = (EnumeratedAttribute) type.newInstance();
		String[] values = ea.getValues();
		String enumerated;
		for (int i = 0; i < values.length; i++) {
			enumerated = values[i].toLowerCase();
			if (prefix.length() == 0 || enumerated.startsWith(prefix)) {
				proposals.add(new AntCompletionProposal(enumerated, cursorPosition - prefix.length(), prefix.length(), enumerated.length(), null, enumerated, null, AntCompletionProposal.TASK_PROPOSAL));
			}
		}
	}

	private void addBooleanAttributeValueProposals(String prefix, List<ICompletionProposal> proposals) {
		String[] booleanValues = new String[] { "true", "false", "on", "off", "yes", "no" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
		String booleanAssist;
		for (int i = 0; i < booleanValues.length; i++) {
			booleanAssist = booleanValues[i].toLowerCase();
			if (prefix.length() == 0 || booleanAssist.startsWith(prefix)) {
				proposals.add(new AntCompletionProposal(booleanAssist, cursorPosition - prefix.length(), prefix.length(), booleanAssist.length(), null, booleanAssist, null, AntCompletionProposal.TASK_PROPOSAL));
			}
		}
	}

	/**
	 * Returns all possible properties for the specified prefix.
	 * <P>
	 * Note that the completion mode must be property mode, otherwise it is not safe to call this method.
	 */
	protected ICompletionProposal[] getPropertyProposals(IDocument document, String prefix, int aCursorPosition) {
		List<ICompletionProposal> proposals = new ArrayList<>();
		Map<String, ICompletionProposal> displayStringToProposals = new HashMap<>();
		Map<String, Object> properties = findPropertiesFromDocument();

		Image image = AntUIImages.getImage(IAntUIConstants.IMG_PROPERTY);
		// Determine replacement length and offset
		// String from beginning to the beginning of the prefix
		int replacementLength = prefix.length();
		int replacementOffset = 0;
		String text = document.get();
		String stringToPrefix = text.substring(0, aCursorPosition - prefix.length());
		// Property proposal
		String lastTwoCharacters = stringToPrefix.substring(stringToPrefix.length() - 2, stringToPrefix.length());
		boolean appendBraces = true;
		if (lastTwoCharacters.equals("${")) { //$NON-NLS-1$
			replacementLength += 2;
			replacementOffset = aCursorPosition - prefix.length() - 2;
		} else if (lastTwoCharacters.endsWith("$")) { //$NON-NLS-1$
			replacementLength += 1;
			replacementOffset = aCursorPosition - prefix.length() - 1;
		} else {
			// support for property proposals for the if/unless attributes of targets
			replacementOffset = aCursorPosition - prefix.length();
			appendBraces = false;
		}

		if (text.length() > aCursorPosition && text.charAt(aCursorPosition) == '}') {
			replacementLength += 1;
		}
		String propertyName;
		for (Iterator<String> i = properties.keySet().iterator(); i.hasNext();) {
			propertyName = i.next();
			if (prefix.length() == 0 || propertyName.toLowerCase().startsWith(prefix)) {
				String additionalPropertyInfo = (String) properties.get(propertyName);

				StringBuffer replacementString = new StringBuffer();
				if (appendBraces) {
					replacementString.append("${"); //$NON-NLS-1$
				}
				replacementString.append(propertyName);
				if (appendBraces) {
					replacementString.append('}');
				}

				if (displayStringToProposals.get(propertyName) == null) {
					ICompletionProposal proposal = new AntCompletionProposal(replacementString.toString(), replacementOffset, replacementLength, replacementString.length(), image, propertyName, additionalPropertyInfo, AntCompletionProposal.PROPERTY_PROPOSAL);
					proposals.add(proposal);
					displayStringToProposals.put(propertyName, proposal);
				}
			}
		}
		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	/**
	 * Returns all possible proposals for the specified parent name.
	 * <P>
	 * No completions will be returned if <code>parentName</code> is not known.
	 * 
	 * @param document
	 *            the entire document
	 * @param parentName
	 *            name of the parent (surrounding) element.
	 * @param prefix
	 *            the prefix that all proposals should start with. The prefix may be an empty string.
	 */
	protected ICompletionProposal[] getTaskProposals(IDocument document, String parentName, String prefix) {
		List<ICompletionProposal> proposals = new ArrayList<>(250);
		ICompletionProposal proposal;
		if (areTasksOrTypesValidChildren(parentName)) {
			// use the definitions in the project as that includes more than what is defined in the DTD
			Project project = antModel.getProjectNode().getProject();
			Map<String, AntTypeDefinition> tasksAndTypes = ComponentHelper.getComponentHelper(project).getAntTypeTable();
			createProposals(document, prefix, proposals, tasksAndTypes);
			if (parentName.equals("project")) { //$NON-NLS-1$
				if ("target".startsWith(prefix)) { //$NON-NLS-1$
					proposals.add(newCompletionProposal(document, prefix, "target")); //$NON-NLS-1$
				}
				if ("extension-point".startsWith(prefix)) { //$NON-NLS-1$
					proposals.add(newCompletionProposal(document, prefix, "extension-point")); //$NON-NLS-1$
				}
			}
		} else {
			IElement parent = getDtd().getElement(parentName);
			if (parent != null) {
				IDfm dfm = parent.getDfm();
				String[] accepts = dfm.getAccepts();
				if (accepts.length == 0) {
					currentProposalMode = PROPOSAL_MODE_NONE;
				}
				String elementName;
				for (int i = 0; i < accepts.length; i++) {
					elementName = accepts[i];
					if (prefix.length() == 0 || elementName.toLowerCase().startsWith(prefix)) {
						proposal = newCompletionProposal(document, prefix, elementName);
						proposals.add(proposal);
					}
				}
			} else {
				// a nested element of a user defined task/type?
				AntTypeDefinition taskClass = getTaskClass(parentName);
				if (taskClass != null) {
					if (MACROINSTANCE_NAME.equals(taskClass.getClassName())) {
						currentProposalMode = PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
						addMacroDefElementProposals(parentName, prefix, proposals);
					} else {
						currentProposalMode = PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL;
						IntrospectionHelper helper = getIntrospectionHelper(taskClass);
						if (helper != null) {
							Enumeration<String> nested = helper.getNestedElements();
							String nestedElement;
							while (nested.hasMoreElements()) {
								nestedElement = nested.nextElement();
								if (prefix.length() == 0 || nestedElement.toLowerCase().startsWith(prefix)) {
									proposal = newCompletionProposal(document, prefix, nestedElement);
									proposals.add(proposal);
								}
							}
						}
					}
				}
			}
		}

		proposal = getClosingTaskProposal(getOpenElementName(), prefix, false);
		if (proposal != null) {
			proposals.add(proposal);
		}

		return proposals.toArray(new ICompletionProposal[proposals.size()]);
	}

	private boolean areTasksOrTypesValidChildren(String parentName) {
		return parentName == "project" || parentName == "target" || parentName == "sequential" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				|| parentName == "presetdef" || parentName == "parallel" || parentName == "daemons" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				|| parentName == "extension-point"; //$NON-NLS-1$
	}

	/**
	 * Returns proposals that define the structure of a build file.
	 * 
	 * Note that template proposals which define the structure of a build file are handled by {@link #determineTemplateProposals(ITextViewer, int)}
	 * which limits proposals by context type.
	 * 
	 * @param document
	 *            the entire document
	 * @param prefix
	 *            the prefix that all proposals should start with. The prefix may be an empty string.
	 */
	protected ICompletionProposal[] getBuildFileProposals(IDocument document, String prefix) {
		String rootElementName = "project"; //$NON-NLS-1$
		IElement rootElement = getDtd().getElement(rootElementName);
		if (rootElement != null && rootElementName.toLowerCase().startsWith(prefix)) {
			ICompletionProposal proposal = newCompletionProposal(document, prefix, rootElementName);
			return new ICompletionProposal[] { proposal };
		}

		return NO_PROPOSALS;
	}

	private void createProposals(IDocument document, String prefix, List<ICompletionProposal> proposals, Map<String, AntTypeDefinition> tasks) {
		Iterator<String> keys = tasks.keySet().iterator();
		ICompletionProposal proposal;
		String key;
		while (keys.hasNext()) {
			key = antModel.getUserNamespaceCorrectName(keys.next());
			if (prefix.length() == 0 || key.toLowerCase().startsWith(prefix)) {
				proposal = newCompletionProposal(document, prefix, key);
				proposals.add(proposal);
			}
		}
	}

	private ICompletionProposal newCompletionProposal(IDocument document, String aPrefix, String elementName) {
		additionalProposalOffset = 0;
		Image proposalImage = AntUIImages.getImage(IAntUIConstants.IMG_TASK_PROPOSAL);
		String proposalInfo = getDescriptionProvider().getDescriptionForTask(elementName);
		boolean hasNestedElements = hasNestedElements(elementName);
		String replacementString = getTaskProposalReplacementString(elementName, hasNestedElements);
		int replacementOffset = cursorPosition - aPrefix.length();
		int replacementLength = aPrefix.length();
		if (replacementOffset > 0 && document.get().charAt(replacementOffset - 1) == '<') {
			replacementOffset--;
			replacementLength++;
		}
		int proposalCursorPosition;
		if (hasNestedElements) {
			proposalCursorPosition = elementName.length() + 2 + additionalProposalOffset;
		} else {
			if (additionalProposalOffset > 0) {
				additionalProposalOffset += 2; // <antstructure output="|"/>
			} else {
				additionalProposalOffset += 1; // <arg|/>
			}
			proposalCursorPosition = elementName.length() + additionalProposalOffset;
		}
		return new AntCompletionProposal(replacementString, replacementOffset, replacementLength, proposalCursorPosition, proposalImage, elementName, proposalInfo, AntCompletionProposal.TASK_PROPOSAL);
	}

	/**
	 * Returns the one possible completion for the specified unclosed task .
	 * 
	 * @param openElementName
	 *            the task that hasn't been closed last
	 * @param prefix
	 *            The prefix that the one possible proposal should start with. The prefix may be an empty string.
	 * @return the proposal or <code>null</code> if no closing proposal available
	 */
	private ICompletionProposal getClosingTaskProposal(String openElementName, String prefix, boolean closingMode) {
		char previousChar = getPreviousChar();
		ICompletionProposal proposal = null;
		if (openElementName != null) {
			if (prefix.length() == 0 || openElementName.toLowerCase().startsWith(prefix)) {
				StringBuffer replaceString = new StringBuffer();
				if (!closingMode) {
					if (previousChar != '/') {
						if (previousChar != '<') {
							replaceString.append('<');
						}
						replaceString.append('/');
					}
				}
				replaceString.append(openElementName);
				replaceString.append('>');
				StringBuffer displayString = new StringBuffer("</"); //$NON-NLS-1$
				displayString.append(openElementName);
				displayString.append('>');
				proposal = new AntCompletionProposal(replaceString.toString(), cursorPosition - prefix.length(), prefix.length(), replaceString.length(), null, displayString.toString(), AntEditorMessages.getString("AntEditorCompletionProcessor.39"), AntCompletionProposal.TAG_CLOSING_PROPOSAL); //$NON-NLS-1$
			}
		}

		return proposal;
	}

	protected char getPreviousChar() {
		ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
		int offset = selection.getOffset();
		char previousChar = '?';
		try {
			previousChar = viewer.getDocument().getChar(offset - 1);
		}
		catch (BadLocationException e) {
			// do nothing
		}
		return previousChar;
	}

	/**
	 * Returns the replacement string for the specified task name.
	 */
	private String getTaskProposalReplacementString(String aTaskName, boolean hasNested) {
		StringBuffer replacement = new StringBuffer("<"); //$NON-NLS-1$
		replacement.append(aTaskName);
		ProposalNode task = getDescriptionProvider().getTaskNode(aTaskName);
		if (task != null) {
			appendRequiredAttributes(replacement, task);
		}
		if (hasNested) {
			replacement.append("></"); //$NON-NLS-1$
			replacement.append(aTaskName);
			replacement.append('>');
		} else {
			replacement.append("/>"); //$NON-NLS-1$
		}
		return replacement.toString();
	}

	private void appendRequiredAttributes(StringBuffer replacement, ProposalNode task) {
		if (task.nodes != null) {
			boolean requiredAdded = false;
			Entry<String, ProposalNode> entry = null;
			for (Iterator<Entry<String, ProposalNode>> i = task.nodes.entrySet().iterator(); i.hasNext();) {
				entry = i.next();
				String name = entry.getKey();
				ProposalNode att = entry.getValue();
				if ("yes".equalsIgnoreCase(att.required)) { //$NON-NLS-1$
					replacement.append(' ');
					replacement.append(name);
					replacement.append("=\"\""); //$NON-NLS-1$
					if (!requiredAdded) {
						additionalProposalOffset = name.length() + 2;
						requiredAdded = true;
					}
				}
			}
		}
	}

	/**
	 * Returns whether the named element supports nested elements.
	 */
	private boolean hasNestedElements(String elementName) {
		IElement element = getDtd().getElement(elementName);
		if (element != null) {
			return !element.isEmpty();
		}
		AntTypeDefinition taskClass = getTaskClass(elementName);
		if (taskClass != null) {
			IntrospectionHelper helper = getIntrospectionHelper(taskClass);
			if (helper != null) {
				Enumeration<String> nested = helper.getNestedElements();
				return nested.hasMoreElements();
			}
		}
		return false;
	}

	/**
	 * Finds a direct child element with <code>aChildElementName</code> of <code>anElement</code>.
	 * <P>
	 * The child will not be searched for in the whole hierarchy but only in the hierarchy step below.
	 * 
	 * @return the found child or <code>null</code> if not found.
	 */
	protected Element findChildElementNamedOf(Element anElement, String aChildElementName) {
		NodeList nodeList = anElement.getChildNodes();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Node childNode = nodeList.item(i);
			if (childNode.getNodeType() == Node.ELEMENT_NODE) {
				if (childNode.getNodeName().equals(aChildElementName)) {
					return (Element) childNode;
				}
			}
		}
		return null;
	}

	/**
	 * Determines the current prefix that should be used for completion.
	 */
	private String getCurrentPrefix() {
		if (currentPrefix != null) {
			return currentPrefix;
		}
		ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
		IDocument doc = viewer.getDocument();
		return getPrefixFromDocument(doc.get(), selection.getOffset() + selection.getLength()).toLowerCase();
	}

	/**
	 * Returns the prefix in the specified document text with respect to the specified offset.
	 * 
	 * @param aDocumentText
	 *            the whole content of the edited file as String
	 * @param anOffset
	 *            the cursor position
	 */
	protected String getPrefixFromDocument(String aDocumentText, int anOffset) {
		if (currentPrefix != null) {
			return currentPrefix;
		}
		int startOfWordToken = anOffset;

		char token = 'a';
		if (startOfWordToken > 0) {
			token = aDocumentText.charAt(startOfWordToken - 1);
		}

		while (startOfWordToken > 0 && (Character.isJavaIdentifierPart(token) || '.' == token || '-' == token || ';' == token) && !('$' == token)) {
			startOfWordToken--;
			if (startOfWordToken == 0) {
				break; // word goes right to the beginning of the doc
			}
			token = aDocumentText.charAt(startOfWordToken - 1);
		}

		if (startOfWordToken != anOffset) {
			currentPrefix = aDocumentText.substring(startOfWordToken, anOffset).toLowerCase();
		} else {
			currentPrefix = IAntCoreConstants.EMPTY_STRING;
		}
		return currentPrefix;
	}

	/**
	 * Returns the current proposal mode.
	 */
	protected int determineProposalMode(IDocument document, int aCursorPosition, String aPrefix) {
		if (currentProposalMode != -1) {
			return currentProposalMode;
		}
		if (document.getLength() == 0 || (document.getLength() == 1 && document.get().equals("<"))) { //$NON-NLS-1$
			return PROPOSAL_MODE_BUILDFILE;
		}

		// String from beginning of document to the beginning of the prefix
		String text = document.get();
		String stringToPrefix = text.substring(0, aCursorPosition - aPrefix.length());
		if (stringToPrefix.length() == 0) {
			return PROPOSAL_MODE_BUILDFILE;
		}
		// Is trimmable from behind
		String trimmedString = stringToPrefix.trim();
		if (antModel != null && antModel.getProjectNode() == null) {
			currentTaskString = getTaskStringFromDocumentStringToPrefix(trimmedString);
			if ("project".equals(currentTaskString)) { //$NON-NLS-1$
				return PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
			}
			return PROPOSAL_MODE_BUILDFILE;
		}

		char lastChar = 0;
		if (trimmedString.length() > 0) {
			lastChar = trimmedString.charAt(trimmedString.length() - 1);
		} else {
			return PROPOSAL_MODE_TASK_PROPOSAL;
		}
		if (stringToPrefix.charAt(stringToPrefix.length() - 1) != lastChar && lastChar != '>' && lastChar != ',') {
			/*
			 * Substring must be trimmable from behind in case of attribute proposal because a space or a new line must be used as delimiter between
			 * task name and attribute or attribute and attribute. Example: '<property id="bla" name="hups"'
			 */

			// Attribute proposal
			if (lastChar != '>' && lastChar != '<') {
				currentTaskString = getTaskStringFromDocumentStringToPrefix(trimmedString);
				if (currentTaskString != null && isKnownElement(currentTaskString)) {
					return PROPOSAL_MODE_ATTRIBUTE_PROPOSAL;
				}
			}
		} else if (stringToPrefix.charAt(stringToPrefix.length() - 1) == '"' || trimmedString.charAt(trimmedString.length() - 1) == ',') {
			// Attribute value proposal
			currentTaskString = getTaskStringFromDocumentStringToPrefix(trimmedString);
			if (currentTaskString != null && isKnownElement(currentTaskString)) {
				return PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL;
			}
		} else { // Possibly a Task proposal
			int spaceIndex = stringToPrefix.lastIndexOf(' ');
			int lessThanIndex = stringToPrefix.lastIndexOf('<');
			int greaterThanIndex = stringToPrefix.lastIndexOf('>');
			// Task proposal
			if (greaterThanIndex < lessThanIndex) {
				// we are inside an open element
				if (lastChar == '$') {
					return PROPOSAL_MODE_PROPERTY_PROPOSAL;
				}
				if (lessThanIndex > spaceIndex) {
					int slashIndex = stringToPrefix.lastIndexOf('/');
					if (slashIndex == lessThanIndex + 1) {
						return PROPOSAL_MODE_TASK_PROPOSAL_CLOSING; // ... </
					}
					return PROPOSAL_MODE_TASK_PROPOSAL;
				}
			}
			if (lessThanIndex < greaterThanIndex) {
				if (isPropertyProposalMode(stringToPrefix)) {
					return PROPOSAL_MODE_PROPERTY_PROPOSAL;
				}
				return PROPOSAL_MODE_TASK_PROPOSAL;
			}
		}

		// Property proposal
		if (isPropertyProposalMode(stringToPrefix)) {
			return PROPOSAL_MODE_PROPERTY_PROPOSAL;
		}

		return PROPOSAL_MODE_NONE;
	}

	private boolean isPropertyProposalMode(String stringToPrefix) {
		if (stringToPrefix.length() >= 2) {
			String lastTwoChars = stringToPrefix.substring(stringToPrefix.length() - 2, stringToPrefix.length());
			if (lastTwoChars.equals("${") || //$NON-NLS-1$
					stringToPrefix.charAt(stringToPrefix.length() - 1) == '$') {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns the last occurring task string in the specified string.
	 * <P>
	 * The returned string must not necessarily be a valid Ant task string. This can be tested with the method <code>inNamedTaskKnown(String)</code>
	 * after invoking this method.
	 * 
	 * @param aDocumentStringToPrefix
	 *            the String that contains the whole string of the currently edited file from the beginning up to the prefix for code completion.
	 *            Example: '<project default="name"><property '.
	 * 
	 * @return the extracted task string or <code>null</code> if no string could be extracted.
	 */
	private String getTaskStringFromDocumentStringToPrefix(String aDocumentStringToPrefix) {

		int lessThanIndex = aDocumentStringToPrefix.lastIndexOf('<');

		if (lessThanIndex > -1) {
			String taskString = aDocumentStringToPrefix.trim();
			taskString = taskString.substring(lessThanIndex + 1, taskString.length());
			int index = taskString.indexOf(' ');
			if (index > 0) {
				taskString = taskString.substring(0, index);
			}
			index = taskString.indexOf('\n');
			if (index > 0) {
				taskString = taskString.substring(0, index);
			}
			index = taskString.indexOf('\r');
			if (index > 0) {
				taskString = taskString.substring(0, index);
			}
			return taskString;
		}

		return null;
	}

	/**
	 * Returns the last occurring attribute string in the specified string. <code>null</code> is returned if no attribute string is available.
	 * <P>
	 * Calling this method is only safe if the current proposal mode is really <code>PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL</code>.
	 */
	public static String getAttributeStringFromDocumentStringToPrefix(String docStringToPrefix) {
		int index = docStringToPrefix.lastIndexOf('=');
		if (index == -1) {
			return null;
		}
		String subString = docStringToPrefix.substring(0, index);
		subString = subString.trim();

		index = subString.lastIndexOf(' ');
		if (index > 0) {
			subString = subString.substring(index + 1, subString.length());
		}
		index = subString.lastIndexOf('\n');
		if (index > 0) {
			subString = subString.substring(index + 1, subString.length());
		}
		index = subString.lastIndexOf('\r');
		if (index > 0) {
			subString = subString.substring(index + 1, subString.length());
		}
		return trimBeginning(subString);
	}

	private static String trimBeginning(String toBeTrimmed) {
		int i = 0;
		while ((i != toBeTrimmed.length()) && Character.isWhitespace(toBeTrimmed.charAt(i))) {
			i++;
		}
		return toBeTrimmed.substring(i);
	}

	/**
	 * Returns whether the specified element name is known
	 */
	protected boolean isKnownElement(String elementName) {
		if (elementName.equals("target") || elementName.equals("project") || elementName.equals("extension-point")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			return true;
		}
		AntProjectNode node = antModel.getProjectNode();
		if (node != null) {
			Project antProject = node.getProject();
			ComponentHelper helper = ComponentHelper.getComponentHelper(antProject);
			if (helper.getDefinition(elementName) != null) {
				return true;
			}
			if (helper.getDefinition(antModel.getNamespaceCorrectName(elementName)) != null) {
				return true;
			}
			// not everything is a task or type (nested elements)
			if (getDtd().getElement(elementName) != null) {
				return true;
			}

			if (getNestedType() != null) {
				return true;
			}
		}

		return false;
	}

	private AntTypeDefinition getTaskClass(String taskName) {
		AntTypeDefinition clss = null;
		AntProjectNode node = antModel.getProjectNode();
		if (node != null) {
			Project antProject = node.getProject();
			Map<String, AntTypeDefinition> tasksAndTypes = ComponentHelper.getComponentHelper(antProject).getAntTypeTable();
			clss = tasksAndTypes.get(taskName);
			if (clss == null) {
				clss = tasksAndTypes.get(antModel.getNamespaceCorrectName(taskName));
			}
		}
		return clss;
	}

	/**
	 * Finds the parent task element in respect to the cursor position.
	 * 
	 * @return the parent task element or <code>null</code> if not found.
	 */
	protected String getParentName(IDocument document, int aLineNumber, int aColumnNumber) {
		if (document.getLength() == 0) {
			return null;
		}
		AntProjectNode project = antModel.getProjectNode();
		if (project == null) {
			return null;
		}
		int offset = getOffset(document, aLineNumber, aColumnNumber);
		if (offset == -1) {
			return null;
		}
		IAntElement node = project.getNode(offset);
		if (node == null) {
			node = antModel.getOpenElement();
		}
		if (node == null) {
			return IAntCoreConstants.EMPTY_STRING;
		} else if (node instanceof AntTaskNode) {
			String name = node.getName();
			if (offset <= node.getOffset() + name.length() - 1) {
				// not really the enclosing node as the offset is within the name of the node
				node = node.getParentNode();
			} else {
				return name;
			}
		}
		if (node instanceof AntTaskNode) {
			return node.getName();
		} else if (node instanceof AntTargetNode) {
			return "target"; //$NON-NLS-1$
		} else {
			return "project"; //$NON-NLS-1$
		}
	}

	/**
	 * Return the properties as defined in the entire buildfile
	 * 
	 * @return a map with all the found properties
	 */
	private Map<String, Object> findPropertiesFromDocument() {
		Project project = antModel.getProjectNode().getProject();
		return project.getProperties();
	}

	private Map<String, Target> getTargets() {
		Project project = antModel.getProjectNode().getProject();
		return project.getTargets();
	}

	protected File getEditedFile() {
		IWorkbenchPage page = AntUIPlugin.getActivePage();
		if (page == null) {
			return null;
		}
		IEditorPart editor = page.getActiveEditor();
		if (editor == null) {
			return null;
		}
		FileEditorInput input = (FileEditorInput) editor.getEditorInput();
		String projectPath = input.getFile().getProject().getLocation().toFile().getAbsolutePath();
		String projectRelativeFilePath = input.getFile().getFullPath().removeFirstSegments(1).makeRelative().toString();
		return new File(projectPath + File.separator + projectRelativeFilePath);
	}

	private String getOpenElementName() {
		AntElementNode node = antModel.getOpenElement();
		if (node == null) {
			return null;
		}
		return node.getName();
	}

	/**
	 * Finds the enclosing target in respect to the cursor position and returns its name
	 * 
	 * @return the name of the enclosing target or <code>null</code> if not found or the element is not contained in a target.
	 */
	private String getEnclosingTargetName(IDocument document, int aLineNumber, int aColumnNumber) {

		AntProjectNode project = antModel.getProjectNode();
		int offset = getOffset(document, aLineNumber, aColumnNumber);
		if (offset == -1) {
			return null;
		}
		IAntElement node = project.getNode(offset);
		if (node instanceof AntTaskNode) {
			node = node.getParentNode();
			if (!(node instanceof AntTargetNode)) {
				// top level task
				node = null;
			}
		} else if (node instanceof AntProjectNode) {
			node = null;
		}
		String targetName = null;
		if (node == null || (targetName = ((AntTargetNode) node).getTarget().getName()) == null || targetName.length() == 0) {
			return null;
		}
		return targetName;
	}

	private int getOffset(IDocument document, int line, int column) {
		try {
			return document.getLineOffset(line) + column - 1;
		}
		catch (BadLocationException e) {
			return -1;
		}
	}

	/**
	 * Sets this processor's set of characters triggering the activation of the completion proposal computation.
	 * 
	 * @param activationSet
	 *            the activation set
	 */
	public void setCompletionProposalAutoActivationCharacters(char[] activationSet) {
		autoActivationChars = activationSet;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#extractPrefix(org.eclipse.jface.text.ITextViewer, int)
	 */
	@Override
	protected String extractPrefix(ITextViewer textViewer, int offset) {
		return getPrefixFromDocument(textViewer.getDocument().get(), offset);
	}

	/**
	 * Cut out angular brackets for relevance sorting, since the template name does not contain the brackets.
	 */
	@Override
	protected int getRelevance(Template template, String prefix) {
		String newprefix = prefix;
		if (newprefix.startsWith("<")) {//$NON-NLS-1$
			newprefix = prefix.substring(1);
		}
		if (template.getName().startsWith(newprefix)) {
			return 90;
		}
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getTemplates(java.lang.String)
	 */
	@Override
	protected Template[] getTemplates(String contextTypeId) {
		return AntTemplateAccess.getDefault().getTemplateStore().getTemplates(contextTypeId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getContextType(org.eclipse.jface.text.ITextViewer,
	 * org.eclipse.jface.text.IRegion)
	 */
	@Override
	protected TemplateContextType getContextType(ITextViewer textViewer, IRegion region) {
		switch (determineProposalMode(textViewer.getDocument(), cursorPosition, getCurrentPrefix())) {
			case PROPOSAL_MODE_TASK_PROPOSAL:
				if (getEnclosingTargetName(textViewer.getDocument(), lineNumber, columnNumber) == null) {
					return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TargetContextType.TARGET_CONTEXT_TYPE);
				}
				return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(TaskContextType.TASK_CONTEXT_TYPE);
			case PROPOSAL_MODE_BUILDFILE:
				return AntTemplateAccess.getDefault().getContextTypeRegistry().getContextType(BuildFileContextType.BUILDFILE_CONTEXT_TYPE);
			case PROPOSAL_MODE_NONE:
			case PROPOSAL_MODE_ATTRIBUTE_PROPOSAL:
			case PROPOSAL_MODE_TASK_PROPOSAL_CLOSING:
			case PROPOSAL_MODE_ATTRIBUTE_VALUE_PROPOSAL:
			case PROPOSAL_MODE_PROPERTY_PROPOSAL:
			case PROPOSAL_MODE_NESTED_ELEMENT_PROPOSAL:
			default:
				return null;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#getImage(org.eclipse.jface.text.templates.Template)
	 */
	@Override
	protected Image getImage(Template template) {
		return AntUIImages.getImage(IAntUIConstants.IMG_TEMPLATE_PROPOSAL);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#createContext(org.eclipse.jface.text.ITextViewer,
	 * org.eclipse.jface.text.IRegion)
	 */
	@Override
	protected TemplateContext createContext(ITextViewer contextViewer, IRegion region) {
		TemplateContextType contextType = getContextType(contextViewer, region);
		if (contextType != null) {
			Point selection = contextViewer.getSelectedRange();
			Position position;
			if (selection.y > 0) {
				position = new Position(selection.x, selection.y);
			} else {
				position = new Position(region.getOffset(), region.getLength());
			}

			IDocument document = contextViewer.getDocument();
			return new AntContext(contextType, document, antModel, position);
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.templates.TemplateCompletionProcessor#createProposal(org.eclipse.jface.text.templates.Template,
	 * org.eclipse.jface.text.templates.TemplateContext, org.eclipse.jface.text.Region, int)
	 */
	@Override
	protected ICompletionProposal createProposal(Template template, TemplateContext context, IRegion region, int relevance) {
		AntTemplateProposal proposal = new AntTemplateProposal(template, context, region, getImage(template), relevance);
		proposal.setInformationControlCreator(new AntTemplateInformationControlCreator());
		return proposal;
	}

	protected ISchema getDtd() {
		if (fgDtd == null) {
			IRunnableWithProgress runnable = new IRunnableWithProgress() {
				@Override
				public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
					try {
						fgDtd = parseDtd();
					}
					catch (IOException e) {
						AntUIPlugin.log(e);
					}
					catch (ParseError e) {
						AntUIPlugin.log(e);
					}
				}
			};

			IProgressService service = PlatformUI.getWorkbench().getProgressService();
			try {
				service.busyCursorWhile(runnable);
			}
			catch (InvocationTargetException e) {
				// do nothing
			}
			catch (InterruptedException e) {
				// do nothing
			}
		}
		return fgDtd;
	}

	/**
	 * The provider for all task and attribute descriptions.
	 */
	private TaskDescriptionProvider getDescriptionProvider() {
		return TaskDescriptionProvider.getDefault();
	}

	protected static void resetCodeCompletionDataStructures() {
		fgDtd = null;
		TaskDescriptionProvider.reset();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionStarted(org.eclipse.jface.text.contentassist.ContentAssistEvent)
	 */
	@Override
	public void assistSessionStarted(ContentAssistEvent event) {
		IContentAssistant assistant = event.assistant;
		if (assistant instanceof IContentAssistantExtension2) {
			fContentAssistant = (IContentAssistantExtension2) assistant;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.contentassist.ICompletionListener#assistSessionEnded(org.eclipse.jface.text.contentassist.ContentAssistEvent)
	 */
	@Override
	public void assistSessionEnded(ContentAssistEvent event) {
		fContentAssistant = null;
		fTemplatesOnly = false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.contentassist.ICompletionListener#selectionChanged(org.eclipse.jface.text.contentassist.ICompletionProposal,
	 * boolean)
	 */
	@Override
	public void selectionChanged(ICompletionProposal proposal, boolean smartToggle) {
		// do nothing
	}

	private String getIterationGestureMessage(String showMessage) {
		final IBindingService bindingSvc = PlatformUI.getWorkbench().getAdapter(IBindingService.class);
		TriggerSequence[] triggers = bindingSvc.getActiveBindingsFor(getContentAssistCommand());
		String message;
		if (triggers.length > 0) {
			message = MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.63"), new Object[] { triggers[0].format(), showMessage }); //$NON-NLS-1$
		} else {
			message = MessageFormat.format(AntEditorMessages.getString("AntEditorCompletionProcessor.64"), new Object[] { showMessage }); //$NON-NLS-1$
		}
		return message;
	}

	private ParameterizedCommand getContentAssistCommand() {
		final ICommandService commandSvc = PlatformUI.getWorkbench().getAdapter(ICommandService.class);
		final Command command = commandSvc.getCommand(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
		ParameterizedCommand pCmd = new ParameterizedCommand(command, null);
		return pCmd;
	}
}