/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Nico Seessle - bug 51332
 *     Alexander Blaas (arctis Softwaretechnologie GmbH) - bug 412809
 *******************************************************************************/

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

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.regex.Pattern;

import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.IntrospectionHelper;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Main;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelperRepository;
import org.apache.tools.ant.RuntimeConfigurable;
import org.apache.tools.ant.Target;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.TaskAdapter;
import org.apache.tools.ant.UnknownElement;
import org.eclipse.ant.core.AntCorePlugin;
import org.eclipse.ant.core.AntCorePreferences;
import org.eclipse.ant.core.AntSecurityException;
import org.eclipse.ant.core.Property;
import org.eclipse.ant.core.Type;
import org.eclipse.ant.internal.core.AntClassLoader;
import org.eclipse.ant.internal.core.AntCoreUtil;
import org.eclipse.ant.internal.core.AntSecurityManager;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.AntUtil;
import org.eclipse.ant.internal.ui.editor.DecayCodeCompletionDataStructuresThread;
import org.eclipse.ant.internal.ui.editor.outline.AntEditorMarkerUpdater;
import org.eclipse.ant.internal.ui.editor.utils.ProjectHelper;
import org.eclipse.ant.internal.ui.preferences.AntEditorPreferenceConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ISynchronizable;
import org.xml.sax.Attributes;
import org.xml.sax.SAXParseException;

import com.ibm.icu.text.MessageFormat;

public class AntModel implements IAntModel {

	private static ClassLoader fgClassLoader;
	private static int fgInstanceCount = 0;
	private static Object loaderLock = new Object();

	private IDocument fDocument;
	private IProblemRequestor fProblemRequestor;
	private LocationProvider fLocationProvider;

	private AntProjectNode fProjectNode;
	private AntTargetNode fCurrentTargetNode;
	private AntElementNode fLastNode;
	private AntElementNode fNodeBeingResolved;
	private int fNodeBeingResolvedIndex = -1;
	private String fEncoding = null;

	private Map<String, String> fEntityNameToPath;

	/**
	 * Stack of still open elements.
	 * <P>
	 * On top of the stack is the innermost element.
	 */
	private Stack<AntElementNode> fStillOpenElements = new Stack<>();

	private Map<Task, AntTaskNode> fTaskToNode = new HashMap<>();

	private List<AntTaskNode> fTaskNodes = new ArrayList<>();

	private final Object fDirtyLock = new Object();
	private boolean fIsDirty = true;
	private File fEditedFile = null;

	private ClassLoader fLocalClassLoader = null;

	private boolean fHasLexicalInfo = true;
	private boolean fHasPositionInfo = true;
	private boolean fHasTaskInfo = true;

	private IDocumentListener fListener;
	private AntEditorMarkerUpdater fMarkerUpdater = null;
	private List<AntElementNode> fNonStructuralNodes = new ArrayList<>(1);

	private IPreferenceChangeListener fCoreListener = new IPreferenceChangeListener() {
		@Override
		public void preferenceChange(PreferenceChangeEvent event) {
			if (IAntCoreConstants.PREFERENCE_CLASSPATH_CHANGED.equals(event.getKey())) {
				if (Boolean.parseBoolean((String) event.getNewValue()) == true) {
					reconcileForPropertyChange(true);
				}
			}
		}
	};
	private IPreferenceChangeListener fUIListener = new IPreferenceChangeListener() {
		@Override
		public void preferenceChange(PreferenceChangeEvent event) {
			String property = event.getKey();
			if (property.equals(AntEditorPreferenceConstants.PROBLEM)) {
				IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntUIPlugin.PI_ANTUI);
				if (node != null) {
					node.removePreferenceChangeListener(fUIListener);
					reconcileForPropertyChange(false);
					node.addPreferenceChangeListener(fUIListener);
				}
			} else if (property.equals(AntEditorPreferenceConstants.CODEASSIST_USER_DEFINED_TASKS)) {
				reconcileForPropertyChange(false);
			} else if (property.equals(AntEditorPreferenceConstants.BUILDFILE_NAMES_TO_IGNORE)
					|| property.equals(AntEditorPreferenceConstants.BUILDFILE_IGNORE_ALL)) {
				fReportingProblemsCurrent = false;
				reconcileForPropertyChange(false);
			}
		}
	};

	private Map<String, String> fProperties = null;
	private List<String> fPropertyFiles = null;

	private Map<String, String> fDefinersToText;
	private Map<String, String> fPreviousDefinersToText;
	private Map<String, List<String>> fDefinerNodeIdentifierToDefinedTasks;
	private Map<String, AntDefiningTaskNode> fTaskNameToDefiningNode;
	private Map<String, String> fCurrentNodeIdentifiers;

	private boolean fReportingProblemsCurrent = false;
	private boolean fDoNotReportProblems = false;
	private boolean fShouldReconcile = true;
	private HashMap<String, String> fNamespacePrefixMappings;

	public AntModel(IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider) {
		init(document, problemRequestor, locationProvider);

		fMarkerUpdater = new AntEditorMarkerUpdater();
		fMarkerUpdater.setModel(this);

		IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntCorePlugin.PI_ANTCORE);
		if (node != null) {
			node.addPreferenceChangeListener(fCoreListener);
		}

		node = InstanceScope.INSTANCE.getNode(AntUIPlugin.PI_ANTUI);
		if (node != null) {
			node.addPreferenceChangeListener(fUIListener);
		}
	}

	public AntModel(IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider, boolean resolveLexicalInfo, boolean resolvePositionInfo, boolean resolveTaskInfo) {
		init(document, problemRequestor, locationProvider);
		fHasLexicalInfo = resolveLexicalInfo;
		fHasPositionInfo = resolvePositionInfo;
		fHasTaskInfo = resolveTaskInfo;
	}

	private void init(IDocument document, IProblemRequestor problemRequestor, LocationProvider locationProvider) {
		fDocument = document;
		fProblemRequestor = problemRequestor;
		fLocationProvider = locationProvider;
		if (fgInstanceCount == 0) {
			// no other models are open to ensure that the classpath is up to date wrt the
			// Ant preferences and start listening for breakpoint changes
			AntDefiningTaskNode.setJavaClassPath();
			AntModelCore.getDefault().startBreakpointListening();
		}
		fgInstanceCount++;
		DecayCodeCompletionDataStructuresThread.cancel();
		ProjectHelper helper = getProjectHelper();
		if (helper == null) {
			ProjectHelperRepository.getInstance().registerProjectHelper(ProjectHelper.class);
		}
		computeEncoding();
	}

	/**
	 * Searches the collection of registered {@link org.apache.tools.ant.ProjectHelper}s to see if we have one registered already.
	 *
	 * @return the {@link ProjectHelper} from our implementation of <code>null</code> if we have not registered one yet
	 * @since 3.7
	 * @see ProjectHelperRepository
	 */
	ProjectHelper getProjectHelper() {
		Iterator<org.apache.tools.ant.ProjectHelper> helpers = ProjectHelperRepository.getInstance().getHelpers();
		while (helpers.hasNext()) {
			org.apache.tools.ant.ProjectHelper helper = helpers.next();
			if (helper instanceof ProjectHelper) {
				return (ProjectHelper) helper;
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#dispose()
	 */
	@Override
	public void dispose() {
		synchronized (getLockObject()) {
			if (fDocument != null && fListener != null) {
				fDocument.removeDocumentListener(fListener);
			}
			fDocument = null;
			fLocationProvider = null;
			ProjectHelper.setAntModel(null);
		}

		IEclipsePreferences node = InstanceScope.INSTANCE.getNode(AntCorePlugin.PI_ANTCORE);
		if (node != null) {
			node.removePreferenceChangeListener(fCoreListener);
		}

		node = InstanceScope.INSTANCE.getNode(AntUIPlugin.PI_ANTUI);
		if (node != null) {
			node.removePreferenceChangeListener(fUIListener);
		}
		fgInstanceCount--;
		if (fgInstanceCount == 0) {
			fgClassLoader = null;
			DecayCodeCompletionDataStructuresThread.getDefault().start();
			AntModelCore.getDefault().stopBreakpointListening();
			cleanup();
		}
	}

	private Object getLockObject() {
		if (fDocument instanceof ISynchronizable) {
			Object lock = ((ISynchronizable) fDocument).getLockObject();
			if (lock != null) {
				return lock;
			}
		}
		return this;
	}

	private void cleanup() {
		AntProjectNode projectNode = getProjectNode();
		if (projectNode != null) {
			// cleanup the introspection helpers that may have been generated
			IntrospectionHelper.clearCache();
			projectNode.getProject().fireBuildFinished(null);
		}
		fEncoding = null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#reconcile()
	 */
	@Override
	public void reconcile() {
		synchronized (fDirtyLock) {
			if (!fShouldReconcile || !fIsDirty) {
				return;
			}
			fIsDirty = false;
		}

		synchronized (getLockObject()) {
			if (fLocationProvider == null) {
				// disposed
				return;
			}

			if (fDocument == null) {
				fProjectNode = null;
			} else {
				reset();
				parseDocument(fDocument);
				reconcileTaskAndTypes();
			}
			AntModelCore.getDefault().notifyAntModelListeners(new AntModelChangeEvent(this));
		}
	}

	private void reset() {
		fCurrentTargetNode = null;
		fStillOpenElements = new Stack<>();
		fTaskToNode = new HashMap<>();
		fTaskNodes = new ArrayList<>();
		fNodeBeingResolved = null;
		fNodeBeingResolvedIndex = -1;
		fLastNode = null;
		fCurrentNodeIdentifiers = null;
		fNamespacePrefixMappings = null;

		fNonStructuralNodes = new ArrayList<>(1);
		if (fDefinersToText != null) {
			fPreviousDefinersToText = new HashMap<>(fDefinersToText);
			fDefinersToText = null;
		}
	}

	private void parseDocument(IDocument input) {
		boolean parsed = true;
		if (input.getLength() == 0) {
			fProjectNode = null;
			parsed = false;
			return;
		}
		ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
		ClassLoader parsingClassLoader = getClassLoader(originalClassLoader);
		Thread.currentThread().setContextClassLoader(parsingClassLoader);
		Project project = null;
		try {
			ProjectHelper projectHelper = null;
			String textToParse = input.get();
			if (fProjectNode == null || !fProjectNode.hasChildren()) {
				fProjectNode = null;
				project = new AntModelProject();
				projectHelper = prepareForFullParse(project, parsingClassLoader);
			} else {
				project = fProjectNode.getProject();
				projectHelper = (ProjectHelper) project.getReference("ant.projectHelper"); //$NON-NLS-1$
				projectHelper.setBuildFile(getEditedFile());
				prepareForFullIncremental();
			}
			beginReporting();
			Map<String, Object> references = project.getReferences();
			references.remove("ant.parsing.context"); //$NON-NLS-1$
			ProjectHelper.setAntModel(this);
			projectHelper.parse(project, textToParse);

		}
		catch (BuildException e) {
			handleBuildException(e, null);
		}
		finally {
			if (parsed) {
				SecurityManager origSM = System.getSecurityManager();
				processAntHome(true);
				try {
					// set a security manager to disallow system exit and system property setting
					System.setSecurityManager(new AntSecurityManager(origSM, Thread.currentThread(), false));
					resolveBuildfile();
					endReporting();
					// clear the additional property-holder(s) to avoid potential memory leaks
					ProjectHelper.clearAdditionalPropertyHolders();
				}
				catch (AntSecurityException e) {
					// do nothing
				}
				finally {
					Thread.currentThread().setContextClassLoader(originalClassLoader);
					getClassLoader(null);
					System.setSecurityManager(origSM);
					project.fireBuildFinished(null); // cleanup (IntrospectionHelper)
				}
			}
		}
	}

	private ProjectHelper prepareForFullParse(Project project, ClassLoader parsingClassLoader) {
		initializeProject(project, parsingClassLoader);
		// Ant's parsing facilities always works on a file, therefore we need
		// to determine the actual location of the file. Though the file
		// contents will not be parsed. We parse the passed document string
		File file = getEditedFile();
		String filePath = IAntCoreConstants.EMPTY_STRING;
		if (file != null) {
			filePath = file.getAbsolutePath();
		}
		project.setUserProperty("ant.file", filePath); //$NON-NLS-1$
		project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$

		ProjectHelper projectHelper = getProjectHelper();
		ProjectHelper.setAntModel(this);
		projectHelper.setBuildFile(file);
		project.addReference("ant.projectHelper", projectHelper); //$NON-NLS-1$
		return projectHelper;
	}

	private void prepareForFullIncremental() {
		fProjectNode.reset();
		fTaskToNode = new HashMap<>();
		fTaskNodes = new ArrayList<>();
	}

	private void initializeProject(Project project, ClassLoader loader) {
		try {
			processAntHome(false);
		}
		catch (AntSecurityException ex) {
			// do nothing - Ant home can not be set from this thread
		}
		project.init();
		setProperties(project);
		setTasks(project, loader);
		setTypes(project, loader);
	}

	private void setTasks(Project project, ClassLoader loader) {
		List<org.eclipse.ant.core.Task> tasks = AntCorePlugin.getPlugin().getPreferences().getTasks();
		for (org.eclipse.ant.core.Task task : tasks) {
			AntTypeDefinition def = new AntTypeDefinition();
			def.setName(task.getTaskName());
			def.setClassName(task.getClassName());
			def.setClassLoader(loader);
			def.setAdaptToClass(Task.class);
			def.setAdapterClass(TaskAdapter.class);
			ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def);
		}
	}

	private void setTypes(Project project, ClassLoader loader) {
		List<Type> types = AntCorePlugin.getPlugin().getPreferences().getTypes();
		for (Type type : types) {
			AntTypeDefinition def = new AntTypeDefinition();
			def.setName(type.getTypeName());
			def.setClassName(type.getClassName());
			def.setClassLoader(loader);
			ComponentHelper.getComponentHelper(project).addDataTypeDefinition(def);
		}
	}

	private void setProperties(Project project) {
		setBuiltInProperties(project);
		setExtraProperties(project);
		setGlobalProperties(project);
		loadExtraPropertyFiles(project);
		loadPropertyFiles(project);
	}

	private void setExtraProperties(Project project) {
		if (fProperties != null) {
			Pattern pattern = Pattern.compile("\\$\\{.*_prompt.*\\}"); //$NON-NLS-1$
			IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
			for (Iterator<String> iter = fProperties.keySet().iterator(); iter.hasNext();) {
				String name = iter.next();
				String value = fProperties.get(name);
				if (!pattern.matcher(value).find()) {
					try {
						value = manager.performStringSubstitution(value);
					}
					catch (CoreException e) {
						// do nothing
					}
				}
				if (value != null) {
					project.setUserProperty(name, value);
				}
			}
		}
	}

	private void loadExtraPropertyFiles(Project project) {
		if (fPropertyFiles != null) {
			try {
				List<Properties> allProperties = AntCoreUtil.loadPropertyFiles(fPropertyFiles, project.getUserProperty("basedir"), getEditedFile().getAbsolutePath()); //$NON-NLS-1$
				setPropertiesFromFiles(project, allProperties);
			}
			catch (IOException e1) {
				AntUIPlugin.log(e1);
			}
		}
	}

	/**
	 * Load all properties from the files
	 */
	private void loadPropertyFiles(Project project) {
		List<String> fileNames = Arrays.asList(AntCorePlugin.getPlugin().getPreferences().getCustomPropertyFiles());
		try {
			List<Properties> allProperties = AntCoreUtil.loadPropertyFiles(fileNames, project.getUserProperty("basedir"), getEditedFile().getAbsolutePath()); //$NON-NLS-1$
			setPropertiesFromFiles(project, allProperties);
		}
		catch (IOException e1) {
			AntUIPlugin.log(e1);
		}
	}

	private void setPropertiesFromFiles(Project project, List<Properties> allProperties) {
		for (Properties props : allProperties) {
			Enumeration<?> propertyNames = props.propertyNames();
			while (propertyNames.hasMoreElements()) {
				String name = (String) propertyNames.nextElement();
				// do not override extra local properties with the global settings
				if (project.getUserProperty(name) == null) {
					project.setUserProperty(name, props.getProperty(name));
				}
			}
		}
	}

	private void setBuiltInProperties(Project project) {
		// set processAntHome for other properties set as system properties
		project.setUserProperty("ant.file", getEditedFile().getAbsolutePath()); //$NON-NLS-1$
		project.setUserProperty("ant.version", Main.getAntVersion()); //$NON-NLS-1$
	}

	private void processAntHome(boolean finished) {
		AntCorePreferences prefs = AntCorePlugin.getPlugin().getPreferences();
		String antHome = prefs.getAntHome();
		if (finished || antHome == null) {
			System.getProperties().remove("ant.home"); //$NON-NLS-1$
			System.getProperties().remove("ant.library.dir"); //$NON-NLS-1$
		} else {
			System.setProperty("ant.home", antHome); //$NON-NLS-1$
			File antLibDir = new File(antHome, "lib"); //$NON-NLS-1$
			System.setProperty("ant.library.dir", antLibDir.getAbsolutePath()); //$NON-NLS-1$
		}
	}

	private void setGlobalProperties(Project project) {
		List<Property> properties = AntCorePlugin.getPlugin().getPreferences().getProperties();
		if (properties != null) {
			for (Iterator<Property> iter = properties.iterator(); iter.hasNext();) {
				Property property = iter.next();
				String value = property.getValue(true);
				if (value != null) {
					project.setUserProperty(property.getName(), value);
				}
			}
		}
	}

	private void resolveBuildfile() {
		Collection<AntTaskNode> nodeCopy = new ArrayList<>(fTaskNodes);
		Iterator<AntTaskNode> iter = nodeCopy.iterator();
		while (iter.hasNext()) {
			AntTaskNode node = iter.next();
			fNodeBeingResolved = node;
			fNodeBeingResolvedIndex = -1;
			if (node.configure(false)) {
				// resolve any new elements that may have been added
				resolveBuildfile();
			}
		}
		fNodeBeingResolved = null;
		fNodeBeingResolvedIndex = -1;
		checkTargets();
	}

	/**
	 * Check that if a default target is specified it exists and that the target dependencies exist.
	 */
	private void checkTargets() {
		if (fProjectNode == null || doNotReportProblems()) {
			return;
		}
		String defaultTargetName = fProjectNode.getDefaultTargetName();
		if (defaultTargetName != null && fProjectNode.getProject().getTargets().get(defaultTargetName) == null) {
			// no default target when one specified (default target does not have to be specified)
			String message = MessageFormat.format(AntModelMessages.AntModel_43, new Object[] { defaultTargetName });
			IProblem problem = createProblem(message, fProjectNode.getOffset(), fProjectNode.getSelectionLength(), AntModelProblem.SEVERITY_ERROR);
			acceptProblem(problem);
			markHierarchy(fProjectNode, AntModelProblem.SEVERITY_ERROR, message);
		}
		if (!fProjectNode.hasChildren()) {
			return;
		}
		List<IAntElement> children = fProjectNode.getChildNodes();
		boolean checkCircularDependencies = true;
		for (IAntElement node : children) {
			IAntElement originalNode = node;
			if (node instanceof AntTargetNode) {
				if (checkCircularDependencies) {
					checkCircularDependencies = false;
					checkCircularDependencies(node);
				}
				checkMissingDependencies(node, originalNode);
			}
		}
	}

	/**
	 * method assumes sender has checked whether to report problems
	 */
	private void checkMissingDependencies(IAntElement node, IAntElement originalNode) {
		String missing = ((AntTargetNode) node).checkDependencies();
		if (missing != null) {
			String message = MessageFormat.format(AntModelMessages.AntModel_44, new Object[] { missing });
			IAntElement importNode = node.getImportNode();
			if (importNode != null) {
				node = importNode;
			}
			IProblem problem = createProblem(message, node.getOffset(), node.getSelectionLength(), AntModelProblem.SEVERITY_ERROR);
			acceptProblem(problem);
			markHierarchy(originalNode, AntModelProblem.SEVERITY_ERROR, message);
		}
	}

	private boolean doNotReportProblems() {
		if (fReportingProblemsCurrent) {
			return fDoNotReportProblems;
		}

		fReportingProblemsCurrent = true;
		fDoNotReportProblems = false;

		if (AntUIPlugin.getDefault().getCombinedPreferenceStore().getBoolean(AntEditorPreferenceConstants.BUILDFILE_IGNORE_ALL)) {
			fDoNotReportProblems = true;
			return fDoNotReportProblems;
		}
		String buildFileNames = AntUIPlugin.getDefault().getCombinedPreferenceStore().getString(AntEditorPreferenceConstants.BUILDFILE_NAMES_TO_IGNORE);
		if (buildFileNames.length() > 0) {
			String[] names = AntUtil.parseString(buildFileNames, ","); //$NON-NLS-1$
			String editedFileName = getEditedFile().getName();
			for (int i = 0; i < names.length; i++) {
				String string = names[i];
				if (string.trim().equals(editedFileName)) {
					fDoNotReportProblems = true;
					return fDoNotReportProblems;
				}
			}
		}

		return fDoNotReportProblems;
	}

	/**
	 * method assumes sendor has checked whether to report problems
	 */
	private void checkCircularDependencies(IAntElement node) {
		Target target = ((AntTargetNode) node).getTarget();
		String name = target.getName();
		if (name == null) {
			return;
		}
		try {
			target.getProject().topoSort(name, target.getProject().getTargets());
		}
		catch (BuildException be) {
			// possible circular dependency
			String message = be.getMessage();
			if (message.startsWith("Circular")) { //$NON-NLS-1$ //we do our own checking for missing dependencies
				IProblem problem = createProblem(message, node.getProjectNode().getOffset(), node.getProjectNode().getSelectionLength(), AntModelProblem.SEVERITY_ERROR);
				acceptProblem(problem);
				markHierarchy(node.getProjectNode(), AntModelProblem.SEVERITY_ERROR, message);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#handleBuildException(org.apache.tools.ant.BuildException,
	 * org.eclipse.ant.internal.ui.model.AntElementNode, int)
	 */
	@Override
	public void handleBuildException(BuildException e, AntElementNode node, int severity) {
		try {
			if (node != null) {
				markHierarchy(node, severity, e.getMessage());
			}
			Location location = e.getLocation();
			int line = 0;
			int originalOffset = 0;
			int nonWhitespaceOffset = 0;
			int length = 0;
			if (location == Location.UNKNOWN_LOCATION && node != null) {
				if (node.getImportNode() != null) {
					node = node.getImportNode();
				}
				nonWhitespaceOffset = node.getOffset();
				length = node.getLength();
			} else {
				line = location.getLineNumber();
				if (line == 0) {
					AntProjectNode projectNode = getProjectNode();
					if (projectNode != null) {
						length = projectNode.getSelectionLength();
						nonWhitespaceOffset = projectNode.getOffset();
						if (severity == AntModelProblem.SEVERITY_ERROR) {
							projectNode.setProblemSeverity(AntModelProblem.NO_PROBLEM);
							projectNode.setProblemMessage(null);
						}
					} else {
						return;
					}
				} else {
					if (node == null) {
						originalOffset = getOffset(line, 1);
						nonWhitespaceOffset = originalOffset;
						try {
							nonWhitespaceOffset = getNonWhitespaceOffset(line, 1);
						}
						catch (BadLocationException be) {
							// do nothing
						}
						length = getLastCharColumn(line) - (nonWhitespaceOffset - originalOffset);
					} else {
						if (node.getImportNode() != null) {
							node = node.getImportNode();
						}
						nonWhitespaceOffset = node.getOffset();
						length = node.getLength();
					}
				}
			}
			notifyProblemRequestor(e, nonWhitespaceOffset, length, severity);
		}
		catch (BadLocationException e1) {
			// do nothing
		}
	}

	public void handleBuildException(BuildException e, AntElementNode node) {
		handleBuildException(e, node, AntModelProblem.SEVERITY_ERROR);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getEditedFile()
	 */
	@Override
	public File getEditedFile() {
		if (fLocationProvider != null && fEditedFile == null) {
			fEditedFile = fLocationProvider.getLocation().toFile();
		}
		return fEditedFile;
	}

	private void markHierarchy(IAntElement openElement, int severity, String message) {
		if (doNotReportProblems()) {
			return;
		}
		while (openElement != null) {
			openElement.setProblemSeverity(severity);
			openElement.setProblemMessage(message);
			openElement = openElement.getParentNode();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getLocationProvider()
	 */
	@Override
	public LocationProvider getLocationProvider() {
		return fLocationProvider;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addTarget(org.apache.tools.ant.Target, int, int)
	 */
	@Override
	public void addTarget(Target newTarget, int line, int column) {
		AntTargetNode targetNode = AntTargetNode.newAntTargetNode(newTarget);
		fProjectNode.addChildNode(targetNode);
		fCurrentTargetNode = targetNode;
		fStillOpenElements.push(targetNode);
		if (fNodeBeingResolved instanceof AntImportNode) {
			targetNode.setImportNode(fNodeBeingResolved);
			targetNode.setExternal(true);
			targetNode.setFilePath(newTarget.getLocation().getFileName());
		} else {
			String targetFileName = newTarget.getLocation().getFileName();
			boolean external = isNodeExternal(targetFileName);
			targetNode.setExternal(external);
			if (external) {
				targetNode.setFilePath(targetFileName);
			}
		}
		computeOffset(targetNode, line, column);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addProject(org.apache.tools.ant.Project, int, int)
	 */
	@Override
	public void addProject(Project project, int line, int column) {
		fProjectNode = new AntProjectNode((AntModelProject) project, this);
		fStillOpenElements.push(fProjectNode);
		computeOffset(fProjectNode, line, column);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addDTD(java.lang.String, int, int)
	 */
	@Override
	public void addDTD(String name, int line, int column) {
		AntDTDNode node = new AntDTDNode(name);
		fStillOpenElements.push(node);
		int offset = -1;
		try {
			if (column <= 0) {
				offset = getOffset(line, 0);
				int lastCharColumn = getLastCharColumn(line);
				offset = computeOffsetUsingPrefix(line, offset, "<!DOCTYPE", lastCharColumn); //$NON-NLS-1$
			} else {
				offset = getOffset(line, column);
			}
		}
		catch (BadLocationException e) {
			AntUIPlugin.log(e);
		}
		node.setOffset(offset);
		fNonStructuralNodes.add(node);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addTask(org.apache.tools.ant.Task, org.apache.tools.ant.Task, org.xml.sax.Attributes, int,
	 * int)
	 */
	@Override
	public void addTask(Task newTask, Task parentTask, Attributes attributes, int line, int column) {
		if (!canGetTaskInfo()) {
			// need to add top level tasks so imports are executed even when
			// the model is not interested in task level resolution
			Target owningTarget = newTask.getOwningTarget();
			String name = owningTarget.getName();
			if (name == null || name.length() != 0) {
				// not the top level implicit target
				return;
			}
		}
		AntTaskNode taskNode = null;
		if (parentTask == null) {
			taskNode = newTaskNode(newTask, attributes);
			if (fCurrentTargetNode == null) {
				fProjectNode.addChildNode(taskNode);
			} else {
				fCurrentTargetNode.addChildNode(taskNode);
			}
		} else {
			taskNode = newNotWellKnownTaskNode(newTask, attributes);
			AntTaskNode parentNode = fTaskToNode.get(parentTask);
			parentNode.addChildNode(taskNode);
		}
		fTaskToNode.put(newTask, taskNode);

		fStillOpenElements.push(taskNode);
		computeOffset(taskNode, line, column);
		if (fNodeBeingResolved instanceof AntImportNode) {
			taskNode.setImportNode(fNodeBeingResolved);
			// place the node in the collection right after the import node
			if (fNodeBeingResolvedIndex == -1) {
				fNodeBeingResolvedIndex = fTaskNodes.indexOf(fNodeBeingResolved);
			}
			fNodeBeingResolvedIndex++;
			fTaskNodes.add(fNodeBeingResolvedIndex, taskNode);
		} else {
			fTaskNodes.add(taskNode);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addEntity(java.lang.String, java.lang.String)
	 */
	@Override
	public void addEntity(String entityName, String entityPath) {
		if (fEntityNameToPath == null) {
			fEntityNameToPath = new HashMap<>();
		}
		fEntityNameToPath.put(entityName, entityPath);
	}

	private AntTaskNode newTaskNode(Task newTask, Attributes attributes) {
		AntTaskNode newNode = null;
		String taskName = newTask.getTaskName();
		if (newTask instanceof UnknownElement) {
			// attempt to handle namespaces
			taskName = ((UnknownElement) newTask).getTag();
		}

		if (isPropertySettingTask(taskName)) {
			newNode = new AntPropertyNode(newTask, attributes);
		} else if (taskName.equalsIgnoreCase("import")) { //$NON-NLS-1$
			newNode = new AntImportNode(newTask, attributes);
		} else if (taskName.equalsIgnoreCase("include")) { //$NON-NLS-1$
			newNode = new AntIncludeNode(newTask, attributes);
		} else if (taskName.equalsIgnoreCase("macrodef") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("presetdef") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("typedef") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("taskdef")) { //$NON-NLS-1$
			newNode = new AntDefiningTaskNode(newTask, attributes);
		} else if (taskName.equalsIgnoreCase("antcall")) { //$NON-NLS-1$
			newNode = new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_TARGET));
		} else if (taskName.equalsIgnoreCase("mkdir")) { //$NON-NLS-1$
			newNode = new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntCoreConstants.DIR));
		} else if (taskName.equalsIgnoreCase("copy")) { //$NON-NLS-1$
			newNode = new AntTaskNode(newTask, generateLabel(taskName, attributes, IAntModelConstants.ATTR_DESTFILE));
		} else if (taskName.equalsIgnoreCase("tar") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("jar") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("war") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("zip")) { //$NON-NLS-1$
			newNode = new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_DESTFILE));
		} else if (taskName.equalsIgnoreCase("untar") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("unjar") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("unwar") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("gunzip") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("bunzip2") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("unzip")) { //$NON-NLS-1$
			newNode = new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_SRC));
		} else if (taskName.equalsIgnoreCase("gzip") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("bzip2")) { //$NON-NLS-1$
			newNode = new AntTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntModelConstants.ATTR_ZIPFILE));
		} else if (taskName.equalsIgnoreCase("exec")) { //$NON-NLS-1$
			String label = "exec "; //$NON-NLS-1$
			String command = attributes.getValue(IAntModelConstants.ATTR_COMMAND);
			if (command != null) {
				label += command;
			}
			command = attributes.getValue(IAntModelConstants.ATTR_EXECUTABLE);
			if (command != null) {
				label += command;
			}
			newNode = new AntTaskNode(newTask, label);
		} else if (taskName.equalsIgnoreCase("ant")) { //$NON-NLS-1$
			newNode = new AntAntNode(newTask, attributes);
		} else if (taskName.equalsIgnoreCase("delete")) { //$NON-NLS-1$
			String label = "delete "; //$NON-NLS-1$
			String file = attributes.getValue(IAntCoreConstants.FILE);
			if (file != null) {
				label += file;
			} else {
				file = attributes.getValue(IAntCoreConstants.DIR);
				if (file != null) {
					label += file;
				}
			}
			newNode = new AntTaskNode(newTask, label);
		} else if (IAntCoreConstants.AUGMENT.equals(taskName)) {
			newNode = new AntAugmentTaskNode(newTask, generateLabel(newTask.getTaskName(), attributes, IAntCoreConstants.ID));
		} else {
			newNode = newNotWellKnownTaskNode(newTask, attributes);
		}
		setExternalInformation(newTask, newNode);
		return newNode;
	}

	/**
	 * @param taskName
	 *            the name of the task to check
	 * @return whether or not a task with this name sets properties
	 */
	private boolean isPropertySettingTask(String taskName) {
		return taskName.equalsIgnoreCase("property") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("available") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("basename") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("condition") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("dirname") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("loadfile") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("pathconvert") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("uptodate") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("xmlproperty") //$NON-NLS-1$
				|| taskName.equalsIgnoreCase("loadproperties"); //$NON-NLS-1$
	}

	private boolean isNodeExternal(String fileName) {
		File taskFile = new File(fileName);
		return !taskFile.equals(getEditedFile());
	}

	private AntTaskNode newNotWellKnownTaskNode(Task newTask, Attributes attributes) {
		AntTaskNode newNode = new AntTaskNode(newTask);
		String id = attributes.getValue("id"); //$NON-NLS-1$
		if (id != null) {
			newNode.setId(id);
		}
		String taskName = newTask.getTaskName();
		if ("attribute".equals(taskName) || "element".equals(taskName)) { //$NON-NLS-1$ //$NON-NLS-2$
			String name = attributes.getValue(IAntCoreConstants.NAME);
			if (name != null) {
				newNode.setBaseLabel(name);
			}
		}

		setExternalInformation(newTask, newNode);
		return newNode;
	}

	private void setExternalInformation(Task newTask, AntTaskNode newNode) {
		String taskFileName = newTask.getLocation().getFileName();
		boolean external = isNodeExternal(taskFileName);
		newNode.setExternal(external);
		if (external) {
			newNode.setFilePath(taskFileName);
		}
	}

	private String generateLabel(String taskName, Attributes attributes, String attributeName) {
		StringBuilder label = new StringBuilder(taskName);
		String srcFile = attributes.getValue(attributeName);
		if (srcFile != null) {
			label.append(' ');
			label.append(srcFile);
		}
		return label.toString();
	}

	private void computeLength(AntElementNode element, int line, int column) {
		if (element.isExternal()) {
			element.setExternalInfo(line, column);
			return;
		}
		try {
			int length;
			int offset;
			if (column <= 0) {
				column = getLastCharColumn(line);
				String lineText = fDocument.get(fDocument.getLineOffset(line - 1), column);
				StringBuilder searchString = new StringBuilder("</"); //$NON-NLS-1$
				searchString.append(element.getName());
				searchString.append('>');
				int index = lineText.indexOf(searchString.toString());
				if (index == -1) {
					index = lineText.indexOf("/>"); //$NON-NLS-1$
					if (index == -1) {
						index = column; // set to the end of line
					} else {
						index = index + 3;
					}
				} else {
					index = index + searchString.length() + 1;
				}
				offset = getOffset(line, index);
			} else {
				offset = getOffset(line, column);
			}

			length = offset - element.getOffset();
			element.setLength(length);
		}
		catch (BadLocationException e) {
			// ignore as the parser may be out of sync with the document during reconciliation
		}
	}

	private void computeOffset(AntElementNode element, int line, int column) {
		if (!canGetPositionInfo()) {
			return;
		}
		if (element.isExternal()) {
			element.setExternalInfo(line - 1, column);
			return;
		}
		try {
			String prefix = "<" + element.getName(); //$NON-NLS-1$
			int offset = computeOffset(line, column, prefix);
			element.setOffset(offset + 1);
			element.setSelectionLength(element.getName().length());
		}
		catch (BadLocationException e) {
			// ignore as the parser may be out of sync with the document during reconciliation
		}
	}

	private int computeOffset(int line, int column, String prefix) throws BadLocationException {
		int offset;
		if (column <= 0) {
			offset = getOffset(line, 0);
			int lastCharColumn = getLastCharColumn(line);
			offset = computeOffsetUsingPrefix(line, offset, prefix, lastCharColumn);
		} else {
			column = column - 1;
			offset = getOffset(line, column);
			offset = computeOffsetUsingPrefix(line, offset, prefix, column);
		}
		return offset;
	}

	private int computeOffsetUsingPrefix(int line, int offset, String prefix, int column) throws BadLocationException {
		String lineText = fDocument.get(fDocument.getLineOffset(line - 1), column);
		int lastIndex = lineText.indexOf(prefix);
		if (lastIndex > -1) {
			offset = getOffset(line, lastIndex + 1);
		} else {
			return computeOffsetUsingPrefix(line - 1, offset, prefix, getLastCharColumn(line - 1));
		}
		return offset;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getOffset(int, int)
	 */
	@Override
	public int getOffset(int line, int column) throws BadLocationException {
		return fDocument.getLineOffset(line - 1) + column - 1;
	}

	private int getNonWhitespaceOffset(int line, int column) throws BadLocationException {
		int offset = fDocument.getLineOffset(line - 1) + column - 1;
		while (Character.isWhitespace(fDocument.getChar(offset))) {
			offset++;
		}
		return offset;
	}

	public int getLine(int offset) {
		try {
			return fDocument.getLineOfOffset(offset) + 1;
		}
		catch (BadLocationException be) {
			return -1;
		}
	}

	private int getLastCharColumn(int line) throws BadLocationException {
		String lineDelimiter = fDocument.getLineDelimiter(line - 1);
		int lineDelimiterLength = lineDelimiter != null ? lineDelimiter.length() : 0;
		return fDocument.getLineLength(line - 1) - lineDelimiterLength;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#setCurrentElementLength(int, int)
	 */
	@Override
	public void setCurrentElementLength(int lineNumber, int column) {
		fLastNode = fStillOpenElements.pop();
		if (fLastNode == fCurrentTargetNode) {
			fCurrentTargetNode = null; // the current target element has been closed
		}
		if (canGetPositionInfo()) {
			computeLength(fLastNode, lineNumber, column);
		}
	}

	private void acceptProblem(IProblem problem) {
		if (fProblemRequestor != null) {
			fProblemRequestor.acceptProblem(problem);
		}
		if (fMarkerUpdater != null) {
			fMarkerUpdater.acceptProblem(problem);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getFile()
	 */
	@Override
	public IFile getFile() {
		IPath location = fLocationProvider.getLocation();
		if (location == null) {
			return null;
		}
		IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(location.toFile().toURI());
		if (files.length > 0) {
			return files[0];
		}
		return null;
	}

	private void beginReporting() {
		if (fProblemRequestor != null) {
			fProblemRequestor.beginReporting();
		}
		if (fMarkerUpdater != null) {
			fMarkerUpdater.beginReporting();
		}
	}

	private void endReporting() {
		if (fProblemRequestor != null) {
			fProblemRequestor.endReporting();
		}
	}

	private IProblem createProblem(Exception exception, int offset, int length, int severity) {
		return createProblem(exception.getMessage(), offset, length, severity);
	}

	private IProblem createProblem(String message, int offset, int length, int severity) {
		return new AntModelProblem(message, severity, offset, length, getLine(offset));
	}

	private void notifyProblemRequestor(Exception exception, IAntElement element, int severity) {
		if (doNotReportProblems()) {
			return;
		}
		IAntElement importNode = element.getImportNode();
		if (importNode != null) {
			element = importNode;
		}
		IProblem problem = createProblem(exception, element.getOffset(), element.getLength(), severity);
		acceptProblem(problem);
		element.setProblem(problem);
	}

	private void notifyProblemRequestor(Exception exception, int offset, int length, int severity) {
		if (doNotReportProblems()) {
			return;
		}
		if (fProblemRequestor != null) {
			IProblem problem = createProblem(exception, offset, length, severity);
			acceptProblem(problem);
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#warning(java.lang.Exception)
	 */
	@Override
	public void warning(Exception exception) {
		handleError(exception, AntModelProblem.SEVERITY_WARNING);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#error(java.lang.Exception)
	 */
	@Override
	public void error(Exception exception) {
		handleError(exception, AntModelProblem.SEVERITY_ERROR);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#errorFromElementText(java.lang.Exception, int, int)
	 */
	@Override
	public void errorFromElementText(Exception exception, int start, int count) {
		AntElementNode node = fLastNode;
		if (node == null) {
			if (!fStillOpenElements.empty()) {
				node = fStillOpenElements.peek();
			}
		}
		if (node == null) {
			return;
		}
		computeEndLocationForErrorNode(node, start, count);
		notifyProblemRequestor(exception, start, count, AntModelProblem.SEVERITY_ERROR);
		markHierarchy(fLastNode, AntModelProblem.SEVERITY_ERROR, exception.getMessage());
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#errorFromElement(java.lang.Exception, org.eclipse.ant.internal.ui.model.AntElementNode, int,
	 * int)
	 */
	@Override
	public void errorFromElement(Exception exception, AntElementNode node, int lineNumber, int column) {
		if (node == null) {
			if (!fStillOpenElements.empty()) {
				node = fStillOpenElements.peek();
			} else {
				node = fLastNode;
			}
		}
		computeEndLocationForErrorNode(node, lineNumber, column);
		notifyProblemRequestor(exception, node, AntModelProblem.SEVERITY_ERROR);
		markHierarchy(node, AntModelProblem.SEVERITY_ERROR, exception.getMessage());
	}

	private AntElementNode createProblemElement(SAXParseException exception) {
		int lineNumber = exception.getLineNumber();
		StringBuilder message = new StringBuilder(exception.getMessage());
		if (lineNumber != -1) {
			message.append(AntModelMessages.AntModel_1 + lineNumber);
		}

		AntElementNode errorNode = new AntElementNode(message.toString());
		errorNode.setFilePath(exception.getSystemId());
		errorNode.setProblemSeverity(AntModelProblem.SEVERITY_ERROR);
		errorNode.setProblemMessage(exception.getMessage());
		computeErrorLocation(errorNode, exception);
		return errorNode;
	}

	private void computeErrorLocation(AntElementNode element, SAXParseException exception) {
		if (element.isExternal()) {
			return;
		}

		int line = exception.getLineNumber();
		int startColumn = exception.getColumnNumber();
		computeEndLocationForErrorNode(element, line, startColumn);
	}

	private void computeEndLocationForErrorNode(IAntElement element, int line, int startColumn) {
		try {
			if (line <= 0) {
				line = 1;
			}
			int endColumn;
			if (startColumn <= 0) {
				if (element.getOffset() > -1) {
					startColumn = element.getOffset() + 1;
				} else {
					startColumn = 1;
				}
				endColumn = getLastCharColumn(line) + 1;
			} else {
				if (startColumn > 1) {
					--startColumn;
				}

				endColumn = startColumn;
				if (startColumn <= getLastCharColumn(line)) {
					++endColumn;
				}
			}

			int correction = 0;
			if (element.getOffset() == -1) {
				int originalOffset = getOffset(line, startColumn);
				int nonWhitespaceOffset = originalOffset;
				try {
					nonWhitespaceOffset = getNonWhitespaceOffset(line, startColumn);
				}
				catch (BadLocationException be) {
					// do nothing
				}
				element.setOffset(nonWhitespaceOffset);
				correction = nonWhitespaceOffset - originalOffset;
			}
			if (endColumn - startColumn == 0) {
				int offset = getOffset(line, startColumn);
				element.setLength(offset - element.getOffset() - correction);
			} else {
				element.setLength(endColumn - startColumn - correction);
			}
		}
		catch (BadLocationException e) {
			// ignore as the parser may be out of sync with the document during reconciliation
		}
	}

	private void handleError(Exception exception, int severity) {
		IAntElement node = null;
		if (fStillOpenElements.isEmpty()) {
			if (exception instanceof SAXParseException) {
				node = createProblemElement((SAXParseException) exception);
			}
		} else {
			node = fStillOpenElements.peek();
		}
		if (node == null) {
			return;
		}
		markHierarchy(node, severity, exception.getMessage());

		if (exception instanceof SAXParseException) {
			SAXParseException parseException = (SAXParseException) exception;
			if (node.getOffset() == -1) {
				computeEndLocationForErrorNode(node, parseException.getLineNumber() - 1, parseException.getColumnNumber());
			} else {
				int lineNumber = parseException.getLineNumber();
				int columnNumber = parseException.getColumnNumber();
				if (columnNumber == -1) {
					columnNumber = 1;
				}
				try {
					AntElementNode childNode = node.getNode(getNonWhitespaceOffset(lineNumber, columnNumber) + 1);
					if (childNode != null && childNode != node) {
						node = childNode;
						node.setProblemSeverity(severity);
						node.setProblemMessage(exception.getMessage());
					} else {
						node = createProblemElement(parseException);
					}
				}
				catch (BadLocationException be) {
					node = createProblemElement(parseException);
				}
			}
		}

		notifyProblemRequestor(exception, node, severity);

		if (node != null) {
			while (node.getParentNode() != null) {
				IAntElement parentNode = node.getParentNode();
				if (parentNode.getLength() == -1) {
					parentNode.setLength(node.getOffset() - parentNode.getOffset() + node.getLength());
				}
				node = parentNode;
			}
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#fatalError(java.lang.Exception)
	 */
	@Override
	public void fatalError(Exception exception) {
		handleError(exception, AntModelProblem.SEVERITY_FATAL_ERROR);
	}

	public AntElementNode getOpenElement() {
		if (fStillOpenElements.isEmpty()) {
			return null;
		}
		return fStillOpenElements.peek();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getEntityName(java.lang.String)
	 */
	@Override
	public String getEntityName(String path) {
		if (fEntityNameToPath != null) {
			Iterator<String> itr = fEntityNameToPath.keySet().iterator();
			String entityPath;
			String name;
			while (itr.hasNext()) {
				name = itr.next();
				entityPath = fEntityNameToPath.get(name);
				if (entityPath.equals(path)) {
					return name;
				}
			}
		}
		return null;
	}

	private ClassLoader getClassLoader(ClassLoader contextClassLoader) {
		synchronized (loaderLock) {
			if (fLocalClassLoader != null) {
				((AntClassLoader) fLocalClassLoader).setPluginContextClassloader(contextClassLoader);
				return fLocalClassLoader;
			}
			if (fgClassLoader == null) {
				fgClassLoader = AntCorePlugin.getPlugin().getNewClassLoader(true);
			}
			if (fgClassLoader instanceof AntClassLoader) {
				((AntClassLoader) fgClassLoader).setPluginContextClassloader(contextClassLoader);
			}
			return fgClassLoader;
		}
	}

	public String getTargetDescription(String targetName) {
		AntTargetNode target = getTargetNode(targetName);
		if (target != null) {
			return target.getTarget().getDescription();
		}
		return null;
	}

	public AntTargetNode getTargetNode(String targetName) {
		AntProjectNode projectNode = getProjectNode();
		if (projectNode == null) {
			return null;
		}
		if (projectNode.hasChildren()) {
			List<IAntElement> possibleTargets = projectNode.getChildNodes();
			for (IAntElement node : possibleTargets) {
				if (node instanceof AntTargetNode) {
					AntTargetNode targetNode = (AntTargetNode) node;
					if (targetName.equalsIgnoreCase(targetNode.getTarget().getName())) {
						return targetNode;
					}
				}
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getProjectNode(boolean)
	 */
	@Override
	public AntProjectNode getProjectNode(boolean doReconcile) {
		if (doReconcile) {
			synchronized (getLockObject()) { // ensure to wait for any current synchronization
				reconcile();
			}
		}
		return fProjectNode;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getProjectNode()
	 */
	@Override
	public AntProjectNode getProjectNode() {
		return getProjectNode(true);
	}

	public AntElementNode getNode(int offset, boolean waitForReconcile) {
		if (getProjectNode(waitForReconcile) != null) {
			return getProjectNode(waitForReconcile).getNode(offset);
		}
		return null;
	}

	/**
	 * Removes any type definitions that no longer exist in the buildfile
	 */
	private void reconcileTaskAndTypes() {
		if (fCurrentNodeIdentifiers == null || fDefinerNodeIdentifierToDefinedTasks == null) {
			return;
		}
		Iterator<String> iter = fDefinerNodeIdentifierToDefinedTasks.keySet().iterator();
		ComponentHelper helper = ComponentHelper.getComponentHelper(fProjectNode.getProject());
		while (iter.hasNext()) {
			String key = iter.next();
			if (fCurrentNodeIdentifiers.get(key) == null) {
				removeDefinerTasks(key, helper.getAntTypeTable());
			}
		}
	}

	protected void removeDefinerTasks(String definerIdentifier, Hashtable<String, AntTypeDefinition> typeTable) {
		if (fDefinerNodeIdentifierToDefinedTasks == null) {
			return;
		}
		List<String> tasks = fDefinerNodeIdentifierToDefinedTasks.get(definerIdentifier);
		if (tasks == null) {
			return;
		}
		Iterator<String> iterator = tasks.iterator();
		while (iterator.hasNext()) {
			typeTable.remove(iterator.next());
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addComment(int, int, int)
	 */
	@Override
	public void addComment(int lineNumber, int columnNumber, int length) {
		AntCommentNode commentNode = new AntCommentNode();
		int offset = -1;
		try {
			offset = computeOffset(lineNumber, columnNumber, "-->"); //$NON-NLS-1$
		}
		catch (BadLocationException e) {
			commentNode.setExternal(true);
			commentNode.setExternalInfo(lineNumber, columnNumber);
			offset = length - 1;
		}
		commentNode.setOffset(offset - length);
		commentNode.setLength(length);
		fNonStructuralNodes.add(commentNode);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#needsTaskResolution()
	 */
	@Override
	public boolean canGetTaskInfo() {
		return fHasTaskInfo;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#needsLexicalResolution()
	 */
	@Override
	public boolean canGetLexicalInfo() {
		return fHasLexicalInfo;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#setClassLoader(java.net.URLClassLoader)
	 */
	@Override
	public void setClassLoader(URLClassLoader loader) {
		AntDefiningTaskNode.setJavaClassPath(loader.getURLs());
		fLocalClassLoader = loader;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#needsPositionResolution()
	 */
	@Override
	public boolean canGetPositionInfo() {
		return fHasPositionInfo;
	}

	public String getPath(String text, int offset) {
		if (fEntityNameToPath != null) {
			String path = fEntityNameToPath.get(text);
			if (path != null) {
				return path;
			}
		}
		AntElementNode node = getNode(offset, true);
		if (node != null) {
			return node.getReferencedElement(offset);
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getText(int, int)
	 */
	@Override
	public String getText(int offset, int length) {
		try {
			return fDocument.get(offset, length);
		}
		catch (BadLocationException e) {
			// do nothing
		}
		return null;
	}

	private IAntElement findPropertyNode(String text, List<IAntElement> children) {
		for (IAntElement element : children) {
			if (element instanceof AntPropertyNode) {
				if (((AntPropertyNode) element).getProperty(text) != null) {
					return element;
				}
			} else if (element.hasChildren()) {
				IAntElement found = findPropertyNode(text, element.getChildNodes());
				if (found != null) {
					return found;
				}
			}
		}
		return null;
	}

	public IAntElement getPropertyNode(String text) {
		AntProjectNode node = getProjectNode();
		if (node == null || !node.hasChildren()) {
			return null;
		}

		return findPropertyNode(text, node.getChildNodes());
	}

	public List<AntElementNode> getNonStructuralNodes() {
		return fNonStructuralNodes;
	}

	public void updateForInitialReconcile() {
		fMarkerUpdater.updateMarkers();
		fShouldReconcile = AntUIPlugin.getDefault().getPreferenceStore().getBoolean(AntEditorPreferenceConstants.EDITOR_RECONCILE);
	}

	public void updateMarkers() {
		boolean temp = fShouldReconcile;
		try {
			fShouldReconcile = true;
			reconcile();
			fMarkerUpdater.updateMarkers();
		}
		finally {
			fShouldReconcile = temp;
		}
	}

	public AntElementNode getReferenceNode(String text) {
		Object reference = getReferenceObject(text);
		if (reference == null) {
			return null;
		}

		Set<Task> nodes = fTaskToNode.keySet();
		Iterator<Task> iter = nodes.iterator();
		while (iter.hasNext()) {
			Task task = iter.next();
			Task tmptask = task;
			if (tmptask instanceof UnknownElement) {
				UnknownElement element = (UnknownElement) tmptask;
				RuntimeConfigurable wrapper = element.getWrapper();
				Map<String, Object> attributes = wrapper.getAttributeMap();
				String id = (String) attributes.get("id"); //$NON-NLS-1$
				if (text.equals(id)) {
					return fTaskToNode.get(task);
				}
			}
		}
		return null;
	}

	public Object getReferenceObject(String refId) {
		AntProjectNode projectNode = getProjectNode();
		if (projectNode == null) {
			return null;
		}
		try {
			Project project = projectNode.getProject();
			Object ref = project.getReference(refId);
			return ref;

		}
		catch (BuildException be) {
			handleBuildException(be, null);
		}
		return null;
	}

	public String getPropertyValue(String propertyName) {
		AntProjectNode projectNode = getProjectNode();
		if (projectNode == null) {
			return null;
		}
		return projectNode.getProject().getProperty(propertyName);
	}

	/**
	 * Only called if the AntModel is associated with an AntEditor
	 */
	public void install() {
		fListener = new IDocumentListener() {
			@Override
			public void documentAboutToBeChanged(DocumentEvent event) {
				synchronized (fDirtyLock) {
					fIsDirty = true;
				}
			}

			@Override
			public void documentChanged(DocumentEvent event) {
				// do nothing
			}
		};
		fDocument.addDocumentListener(fListener);
	}

	private void reconcileForPropertyChange(boolean classpathChanged) {
		if (classpathChanged) {
			fProjectNode = null; // need to reset tasks, types and properties
			fgClassLoader = null;
			AntDefiningTaskNode.setJavaClassPath();
			ProjectHelper.reset();
		}
		fIsDirty = true;
		reconcile();
		AntModelCore.getDefault().notifyAntModelListeners(new AntModelChangeEvent(this, true));
		fMarkerUpdater.updateMarkers();
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#setProperties(java.util.Map)
	 */
	@Override
	public void setProperties(Map<String, String> properties) {
		fProperties = properties;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#setPropertyFiles(java.util.List)
	 */
	@Override
	public void setPropertyFiles(String[] propertyFiles) {
		if (propertyFiles != null) {
			fPropertyFiles = Arrays.asList(propertyFiles);
		}
	}

	@Override
	public void setDefiningTaskNodeText(AntDefiningTaskNode node) {
		if (fDefinersToText == null) {
			fDefinersToText = new HashMap<>();
			fCurrentNodeIdentifiers = new HashMap<>();
		}

		String nodeIdentifier = node.getIdentifier();
		String nodeText = null;
		if (fPreviousDefinersToText != null) {
			nodeText = fPreviousDefinersToText.get(nodeIdentifier);
		}
		String newNodeText = getText(node.getOffset(), node.getLength());
		if (nodeText != null) {
			if (nodeText.equals(newNodeText)) {
				node.setNeedsToBeConfigured(false);
				// update the data structures for the new node as the offset may have changed.
				List<String> tasks = fDefinerNodeIdentifierToDefinedTasks.get(nodeIdentifier);
				if (tasks != null) {
					for (Iterator<String> iter = tasks.iterator(); iter.hasNext();) {
						String taskName = iter.next();
						fTaskNameToDefiningNode.put(taskName, node);
					}
				}
			}
		}

		if (newNodeText != null) {
			fDefinersToText.put(nodeIdentifier, newNodeText);
		}
		fCurrentNodeIdentifiers.put(nodeIdentifier, nodeIdentifier);
	}

	protected void removeDefiningTaskNodeInfo(AntDefiningTaskNode node) {
		Object identifier = node.getIdentifier();
		if (identifier != null && fCurrentNodeIdentifiers != null) {
			fCurrentNodeIdentifiers.remove(identifier);
			fDefinersToText.remove(identifier);
		}
	}

	protected void addDefinedTasks(List<String> newTasks, AntDefiningTaskNode node) {
		if (fTaskNameToDefiningNode == null) {
			fTaskNameToDefiningNode = new HashMap<>();
			fDefinerNodeIdentifierToDefinedTasks = new HashMap<>();
		}

		String identifier = node.getIdentifier();
		if (identifier == null) {
			return;
		}
		if (newTasks.isEmpty() && fCurrentNodeIdentifiers != null) {
			fCurrentNodeIdentifiers.remove(identifier);
		}
		fDefinerNodeIdentifierToDefinedTasks.put(identifier, newTasks);
		Iterator<String> iter = newTasks.iterator();
		while (iter.hasNext()) {
			String name = iter.next();
			fTaskNameToDefiningNode.put(name, node);
		}
	}

	public AntDefiningTaskNode getDefininingTaskNode(String nodeName) {
		if (fTaskNameToDefiningNode != null) {
			AntDefiningTaskNode node = fTaskNameToDefiningNode.get(nodeName);
			if (node == null) {
				nodeName = getNamespaceCorrectName(nodeName);
				node = fTaskNameToDefiningNode.get(nodeName);
			}
			return node;
		}
		return null;
	}

	public String getNamespaceCorrectName(String nodeName) {
		String prefix = org.apache.tools.ant.ProjectHelper.extractUriFromComponentName(nodeName);
		String uri = getPrefixMapping(prefix);
		nodeName = org.apache.tools.ant.ProjectHelper.genComponentName(uri, org.apache.tools.ant.ProjectHelper.extractNameFromComponentName(nodeName));
		return nodeName;
	}

	public String getUserNamespaceCorrectName(String nodeName) {
		String prefix = org.apache.tools.ant.ProjectHelper.extractUriFromComponentName(nodeName);
		if (prefix.length() > 0) {
			String uri = getUserPrefixMapping(prefix);
			nodeName = org.apache.tools.ant.ProjectHelper.genComponentName(uri, org.apache.tools.ant.ProjectHelper.extractNameFromComponentName(nodeName));
		}
		return nodeName;
	}

	public AntTaskNode getMacroDefAttributeNode(String macroDefAttributeName) {
		if (fTaskNameToDefiningNode == null) {
			return null;
		}
		for (AntDefiningTaskNode definingNode : fTaskNameToDefiningNode.values()) {
			List<IAntElement> attributes = definingNode.getChildNodes();
			if (attributes != null) {
				for (IAntElement element : attributes) {
					if (macroDefAttributeName.equals(element.getLabel())) {
						return (AntTaskNode) element;
					}
				}
			}
		}
		return null;
	}

	/**
	 * Sets whether the AntModel should reconcile if it become dirty. If set to reconcile, a reconcile is triggered if the model is dirty.
	 *
	 * @param shouldReconcile
	 */
	public void setShouldReconcile(boolean shouldReconcile) {
		fShouldReconcile = shouldReconcile;
		if (fShouldReconcile) {
			reconcile();
		}
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#addPrefixMapping(java.lang.String, java.lang.String)
	 */
	@Override
	public void addPrefixMapping(String prefix, String uri) {
		if (fNamespacePrefixMappings == null) {
			fNamespacePrefixMappings = new HashMap<>();
		}
		fNamespacePrefixMappings.put(prefix, uri);
	}

	private String getPrefixMapping(String prefix) {
		if (fNamespacePrefixMappings != null) {
			return fNamespacePrefixMappings.get(prefix);
		}
		return null;
	}

	private String getUserPrefixMapping(String prefix) {
		if (fNamespacePrefixMappings != null) {
			Set<Entry<String, String>> entrySet = fNamespacePrefixMappings.entrySet();
			Iterator<Entry<String, String>> entries = entrySet.iterator();
			while (entries.hasNext()) {
				Map.Entry<String, String> entry = entries.next();
				if (entry.getValue().equals(prefix)) {
					return entry.getKey();
				}
			}
		}
		return null;
	}

	/**
	 * Compute the encoding for the backing build file
	 *
	 * @since 3.7
	 */
	void computeEncoding() {
		try {
			IFile file = getFile();
			if (file != null) {
				fEncoding = getFile().getCharset(true);
				return;
			}
		}
		catch (CoreException e) {
			// do nothing. default to UTF-8
		}
		// try the file buffer manager - likely an external file
		IPath path = getLocationProvider().getLocation();
		if (path != null) {
			File buildfile = path.toFile();
			try (FileReader reader = new FileReader(buildfile)) {
				QualifiedName[] options = new QualifiedName[] { IContentDescription.CHARSET };
				IContentDescription desc = Platform.getContentTypeManager().getDescriptionFor(reader, buildfile.getName(), options);
				if (desc != null) {
					fEncoding = desc.getCharset();
					return;
				}
			}
			catch (IOException ioe) {
				// do nothing
			}
		}
		fEncoding = IAntCoreConstants.UTF_8;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see org.eclipse.ant.internal.ui.model.IAntModel#getEncoding()
	 */
	@Override
	public String getEncoding() {
		return fEncoding;
	}
}