/*******************************************************************************
 * Copyright (c) 2002, 2015 GEBIT Gesellschaft fuer EDV-Beratung
 * und Informatik-Technologien mbH, 
 * Berlin, Duesseldorf, Frankfurt (Germany) and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     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<ICompletionProposal>(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<ICompletionProposal>();
		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<AntCompletionProposal>(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<ICompletionProposal>(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<ICompletionProposal>();
		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<ICompletionProposal>(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>();
		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<ICompletionProposal>(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<ICompletionProposal>();
		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<ICompletionProposal>();
		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<ICompletionProposal>();
		Map<String, ICompletionProposal> displayStringToProposals = new HashMap<String, ICompletionProposal>();
		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<ICompletionProposal>(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;
	}
}