/*******************************************************************************
 * Copyright (c) 2005, 2017 IBM Corporation 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
 *
 *******************************************************************************/
package org.eclipse.dltk.core.tests.model;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.ElementChangedEvent;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IElementChangedListener;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IModelElementDelta;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.IProblemRequestor;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptModel;
import org.eclipse.dltk.core.IScriptModelMarker;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.WorkingCopyOwner;
import org.eclipse.dltk.core.tests.FileUtil;
import org.eclipse.dltk.core.tests.WorkspaceAutoBuild;
import org.eclipse.dltk.internal.core.BuildpathEntry;
import org.eclipse.dltk.internal.core.ModelElement;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.dltk.internal.core.util.Util;
import org.eclipse.dltk.internal.core.util.Util.Comparer;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;

public abstract class AbstractModelTests extends SuiteOfTestCases {
	protected boolean displayName = false;
	protected String endChar = ",";

	// infos for invalid results
	protected int tabs = 2;

	// working copies usage
	protected ISourceModule[] workingCopies;

	protected WorkingCopyOwner wcOwner;

	protected boolean discard;

	protected String fTestProjectName = "org.eclipse.dltk.core.tests";

	class DeltaListener implements IElementChangedListener {
		IModelElementDelta[] deltas;

		@Override
		public void elementChanged(ElementChangedEvent ev) {
			IModelElementDelta[] copy = new IModelElementDelta[deltas.length
					+ 1];
			System.arraycopy(deltas, 0, copy, 0, deltas.length);
			copy[deltas.length] = ev.getDelta();
			deltas = copy;
		}

		@Override
		public String toString() {
			StringBuffer buffer = new StringBuffer();
			for (int i = 0, length = this.deltas.length; i < length; i++) {
				IModelElementDelta delta = this.deltas[i];
				IModelElementDelta[] children = delta.getAffectedChildren();
				int childrenLength = children.length;
				IResourceDelta[] resourceDeltas = delta.getResourceDeltas();
				int resourceDeltasLength = resourceDeltas == null ? 0
						: resourceDeltas.length;
				if (childrenLength == 0 && resourceDeltasLength == 0) {
					buffer.append(delta);
				} else {
					sortDeltas(children);
					for (int j = 0; j < childrenLength; j++) {
						buffer.append(children[j]);
						if (j != childrenLength - 1) {
							buffer.append("\n");
						}
					}
					for (int j = 0; j < resourceDeltasLength; j++) {
						if (j == 0 && buffer.length() != 0) {
							buffer.append("\n");
						}
						buffer.append(resourceDeltas[j]);
						if (j != resourceDeltasLength - 1) {
							buffer.append("\n");
						}
					}
				}
				if (i != length - 1) {
					buffer.append("\n\n");

				}
			}
			return buffer.toString();
		}

		protected void sortDeltas(IModelElementDelta[] elementDeltas) {
			Comparer comparer = (a, b) -> {
				IModelElementDelta deltaA = (IModelElementDelta) a;
				IModelElementDelta deltaB = (IModelElementDelta) b;
				return deltaA.getElement().getElementName()
						.compareTo(deltaB.getElement().getElementName());
			};
			org.eclipse.dltk.internal.core.util.Util.sort(elementDeltas,
					comparer);
		}
	}

	protected DeltaListener deltaListener = new DeltaListener();

	public AbstractModelTests(String testProjectName, String name) {
		super(name);
		this.fTestProjectName = testProjectName;
	}

	public AbstractModelTests(String testProjectName, String name, int tabs) {
		super(name);
		this.fTestProjectName = testProjectName;
		this.tabs = tabs;
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		if (this.discard) {
			this.workingCopies = null;
		}
		this.discard = true;
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		if (this.discard && this.workingCopies != null) {
			discardWorkingCopies(this.workingCopies);
			this.wcOwner = null;
		}
	}

	public File getSourceWorkspacePath() {
		return new File(getPluginDirectoryPath(), "workspace");
	}

	/**
	 * Returns the OS path to the directory that contains this plugin.
	 */
	protected File getPluginDirectoryPath() {
		try {
			final Bundle bundle = Platform.getBundle(this.fTestProjectName);
			if (bundle == null) {
				throw new IllegalStateException(
						NLS.bind("Bundle \"{0}\" with test data not found",
								fTestProjectName));
			}
			URL platformURL = bundle.getEntry("/");
			return new File(FileLocator.toFileURL(platformURL).getFile());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Copy the given source directory (and all its contents) to the given
	 * target directory.
	 */
	protected void copyDirectory(File source, File target) throws IOException {
		FileUtil.copyDirectory(source, target);
	}

	/**
	 * Copy file from src (path to the original file) to dest (path to the
	 * destination file).
	 */
	public static void copy(File src, File dest) throws IOException {
		FileUtil.copyFile(src, dest);
	}

	public IProject setUpProject(final String projectName)
			throws CoreException, IOException {
		return setUpProjectTo(projectName, projectName);
	}

	protected IScriptProject setUpScriptProjectTo(final String projectName,
			final String fromName) throws CoreException, IOException {
		final IProject project = setUpProjectTo(projectName, fromName);
		return DLTKCore.create(project);
	}

	protected IProject setUpProjectTo(final String projectName,
			final String fromName) throws CoreException, IOException {
		// copy files in project from source workspace to target workspace
		final File sourceWorkspacePath = getSourceWorkspacePath();
		final File targetWorkspacePath = getWorkspaceRoot().getLocation()
				.toFile();

		final File source = new File(sourceWorkspacePath, fromName);
		if (!source.isDirectory()) {
			throw new IllegalArgumentException(
					NLS.bind("Source directory \"{0}\" doesn't exist", source));
		}
		copyDirectory(source, new File(targetWorkspacePath, projectName));

		return createProject(projectName);
	}

	protected IScriptProject setUpScriptProject(final String projectName)
			throws CoreException, IOException {
		final IProject project = setUpProject(projectName);
		return DLTKCore.create(project);
	}

	/**
	 * Returns the specified source module in the given project, root, and
	 * folder or <code>null</code> if it does not exist.
	 */
	public ISourceModule getSourceModule(String projectName, String rootPath,
			IPath path) throws ModelException {
		IScriptFolder folder = getScriptFolder(projectName, rootPath,
				path.removeLastSegments(1));
		if (folder == null) {
			return null;
		}
		return folder.getSourceModule(path.lastSegment());
	}

	public ISourceModule getSourceModule(String projectName, String rootPath,
			String path) throws ModelException {
		IScriptFolder folder = getScriptFolder(projectName, rootPath,
				new Path(path).removeLastSegments(1));
		if (folder == null) {
			return null;
		}
		return folder.getSourceModule(new Path(path).lastSegment().toString());
	}

	/**
	 * Returns the specified script folder in the given project and fragment, or
	 * <code>null</code> if it does not exist. The rootPath must be specified as
	 * a project relative path. The empty path refers to the default package
	 * fragment.
	 */
	public IScriptFolder getScriptFolder(String projectName,
			String fragmentPath, IPath path) throws ModelException {
		IProjectFragment root = getProjectFragment(projectName, fragmentPath);
		if (root == null) {
			return null;
		}
		return root.getScriptFolder(path);
	}

	/**
	 * Returns the specified package fragment root in the given project, or
	 * <code>null</code> if it does not exist. If relative, the rootPath must be
	 * specified as a project relative path. The empty path refers to the
	 * package fragment root that is the project folder iteslf. If absolute, the
	 * rootPath refers to either an external zip, or a resource internal to the
	 * workspace
	 */
	public IProjectFragment getProjectFragment(String projectName,
			String fragmentPath) throws ModelException {

		IScriptProject project = getScriptProject(projectName);
		if (project == null) {
			return null;
		}
		IPath path = Path.fromPortableString(fragmentPath);
		if (path.isAbsolute() && path.getDevice() == null) {
			IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace()
					.getRoot();
			IResource resource = workspaceRoot.findMember(path);
			IProjectFragment root;
			// resource in the workspace
			root = project.getProjectFragment(resource);
			return root;
		} else {
			IProjectFragment[] roots = project.getProjectFragments();
			if (roots == null || roots.length == 0) {
				return null;
			}
			for (int i = 0; i < roots.length; i++) {
				IProjectFragment root = roots[i];
				IResource underlyingResource = root.getUnderlyingResource();
				if (underlyingResource != null && underlyingResource
						.getProjectRelativePath().equals(path)) {
					return root;
				}
				if (root.getPath().equals(path)) {
					return root;
				}
			}
		}
		return null;
	}

	/**
	 * Returns the script Project with the given name in this test suite's
	 * model. This is a convenience method.
	 */
	public IScriptProject getScriptProject(String name) {
		IProject project = getProject(name);
		return DLTKCore.create(project);
	}

	protected void discardWorkingCopies(ISourceModule[] units)
			throws ModelException {
		if (units == null)
			return;
		for (int i = 0, length = units.length; i < length; i++)
			if (units[i] != null)
				units[i].discardWorkingCopy();
	}

	@Override
	public void setUpSuite() throws Exception {
		super.setUpSuite();

		// ensure autobuilding is turned off
		WorkspaceAutoBuild.disable();
	}

	/**
	 * Deprecated since 2012-01-11 because of the typo in method name.
	 */
	@Deprecated
	public static void disableAutoBulid() throws CoreException {
		WorkspaceAutoBuild.disable();
	}

	protected ISourceModule getSourceModule(String path) {
		return (ISourceModule) DLTKCore.create(getFile(path));
	}

	protected IFile getFile(String path) {
		return getWorkspaceRoot().getFile(new Path(path));
	}

	protected IFolder getFolder(IPath path) {
		return getWorkspaceRoot().getFolder(path);
	}

	protected void deleteFolder(IPath folderPath) throws CoreException {
		deleteResource(getFolder(folderPath));
	}

	/**
	 * Returns the IWorkspace this test suite is running on.
	 */
	public static IWorkspace getWorkspace() {
		return ResourcesPlugin.getWorkspace();
	}

	public static IWorkspaceRoot getWorkspaceRoot() {
		return getWorkspace().getRoot();
	}

	public static IProject getProject(String project) {
		return getWorkspaceRoot().getProject(project);
	}

	/*
	 * Create simple project.
	 */
	protected IProject createProject(final String projectName)
			throws CoreException {
		final IProject project = getProject(projectName);
		IWorkspaceRunnable create = monitor -> {
			project.create(null);
			project.open(null);
		};
		getWorkspace().run(create, null);
		return project;
	}

	/*
	 * Creates a script project with the given source folders an output
	 * location. Add those on the project's buildpath.
	 */
	protected IScriptProject createScriptProject(String projectName,
			String[] natures, String[] sourceFolders) throws CoreException {
		return createScriptProject(projectName, natures, sourceFolders, null);
	}

	protected IScriptProject createScriptProject(final String projectName,
			final String[] natures, final String[] sourceFolders,
			final String[] projects) throws CoreException {
		return createScriptProject(projectName, natures, sourceFolders,
				projects, null);
	}

	/*
	 * Creates a script project with the given source folders an output
	 * location. Add those on the project's buildpath.
	 */
	protected IScriptProject createScriptProject(final String projectName,
			final String[] natures, final String[] sourceFolders,
			final String[] projects, final String[] containers)
			throws CoreException {
		final IScriptProject[] result = new IScriptProject[1];
		IWorkspaceRunnable create = monitor -> {
			// create project
			createProject(projectName);

			IProject project = getWorkspaceRoot().getProject(projectName);

			// add natures
			IProjectDescription description = project.getDescription();
			description.setNatureIds(natures);
			project.setDescription(description, null);

			// create buildpath entries
			IPath projectPath = project.getFullPath();
			int sourceLength = sourceFolders == null ? 0 : sourceFolders.length;
			int containersLength = containers == null ? 0 : containers.length;
			int projectLength = projects == null ? 0 : projects.length;
			IBuildpathEntry[] entries = new IBuildpathEntry[sourceLength
					+ projectLength + containersLength];
			for (int i1 = 0; i1 < sourceLength; i1++) {
				IPath sourcePath = new Path(sourceFolders[i1]);
				int segmentCount = sourcePath.segmentCount();
				if (segmentCount > 0) {
					// create folder and its parents
					IContainer container = project;
					for (int j = 0; j < segmentCount; j++) {
						IFolder folder = container
								.getFolder(new Path(sourcePath.segment(j)));
						if (!folder.exists()) {
							folder.create(true, true, null);
						}
						container = folder;
					}
				}
				// create source entry
				entries[i1] = DLTKCore
						.newSourceEntry(projectPath.append(sourcePath));
			}

			for (int i2 = 0; i2 < projectLength; i2++) {

				// accessible files
				IPath[] accessibleFiles;
				accessibleFiles = new IPath[0];

				// non accessible files
				IPath[] nonAccessibleFiles;
				nonAccessibleFiles = new IPath[0];

				entries[sourceLength + i2] = DLTKCore.newProjectEntry(
						new Path(projects[i2]),
						BuildpathEntry.getAccessRules(accessibleFiles,
								nonAccessibleFiles),
						true, new IBuildpathAttribute[0], false);
			}

			for (int i3 = 0; i3 < containersLength; i3++) {
				entries[sourceLength + projectLength + i3] = DLTKCore
						.newContainerEntry(new Path(containers[i3]));
			}
			// set buildpath and output location
			IScriptProject scriptProject = DLTKCore.create(project);
			scriptProject.setRawBuildpath(entries, null);

			result[0] = scriptProject;
		};
		getWorkspace().run(create, null);
		return result[0];
	}

	/*
	 * Asserts that the given actual source (usually coming from a file content)
	 * is equal to the expected one. Note that 'expected' is assumed to have the
	 * '\n' line separator. The line separators in 'actual' are converted to
	 * '\n' before the comparison.
	 */
	protected void assertSourceEquals(String message, String expected,
			String actual) {
		if (actual == null) {
			assertEquals(message, expected, null);
			return;
		}
		actual = org.eclipse.dltk.core.tests.util.Util
				.convertToIndependantLineDelimiter(actual);
		if (!actual.equals(expected)) {
			System.out.print(org.eclipse.dltk.core.tests.util.Util
					.displayString(actual.toString(), 2));
			System.out.println(this.endChar);
		}
		assertEquals(message, expected, actual);
	}

	/**
	 * Delete this resource.
	 */
	public static void deleteResource(IResource resource) throws CoreException {
		CoreException lastException = null;
		try {
			resource.delete(true, null);
		} catch (CoreException e) {
			lastException = e;
			// just print for info
			System.out.println(e.getMessage());
		} catch (IllegalArgumentException iae) {
			// just print for info
			System.out.println(iae.getMessage());
		}
		int retryCount = 60; // wait 1 minute at most
		while (resource.isAccessible() && --retryCount >= 0) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			try {
				resource.delete(true, null);
			} catch (CoreException e) {
				lastException = e;
				// just print for info
				System.out
						.println("Retry " + retryCount + ": " + e.getMessage());
			} catch (IllegalArgumentException iae) {
				// just print for info
				System.out.println(
						"Retry " + retryCount + ": " + iae.getMessage());
			}
		}
		if (!resource.isAccessible())
			return;
		System.err.println("Failed to delete " + resource.getFullPath());
		if (lastException != null) {
			throw lastException;
		}
	}

	protected IFolder createFolder(IPath path) throws CoreException {
		final IFolder folder = getWorkspaceRoot().getFolder(path);
		getWorkspace().run(monitor -> {
			IContainer parent = folder.getParent();
			if (parent instanceof IFolder && !parent.exists()) {
				createFolder(parent.getFullPath());
			}
			folder.create(true, true, null);
		}, null);

		return folder;
	}

	public static void deleteProject(String projectName) throws CoreException {
		IProject project = getProject(projectName);
		if (project.exists() && !project.isOpen()) { // force opening so that
			// project can be
			// deleted without
			// logging (see bug
			// 23629)
			project.open(null);
		}
		deleteResource(project);
	}

	/**
	 * Batch deletion of projects
	 */
	protected void deleteProjects(final String... projectNames)
			throws CoreException {
		ResourcesPlugin.getWorkspace().run(monitor -> {
			if (projectNames != null) {
				for (int i = 0, max = projectNames.length; i < max; i++) {
					if (projectNames[i] != null)
						deleteProject(projectNames[i]);
				}
			}
		}, null);
	}

	/**
	 * Starts listening to element deltas, and queues them in fgDeltas.
	 */
	public void startDeltas() {
		clearDeltas();
		DLTKCore.addElementChangedListener(this.deltaListener);
	}

	/**
	 * Stops listening to element deltas, and clears the current deltas.
	 */
	public void stopDeltas() {
		DLTKCore.removeElementChangedListener(this.deltaListener);
		clearDeltas();
	}

	/**
	 * Empties the current deltas.
	 */
	public void clearDeltas() {
		this.deltaListener.deltas = new IModelElementDelta[0];
	}

	protected void sortElements(IModelElement[] elements) {
		Comparer comparer = (a, b) -> {
			ModelElement elementA = (ModelElement) a;
			ModelElement elementB = (ModelElement) b;
			// char[] tempJCLPath = "<externalJCLPath>".toCharArray();
			// String idA = new String(CharOperation.replace(
			// elementA.toStringWithAncestors().toCharArray(),
			// getExternalJCLPathString().toCharArray(),
			// tempJCLPath));
			// String idB = new String(CharOperation.replace(
			// elementB.toStringWithAncestors().toCharArray(),
			// getExternalJCLPathString().toCharArray(),
			// tempJCLPath));
			return elementA.toStringWithAncestors()
					.compareTo(elementB.toStringWithAncestors().toString());
			// return idA.compareTo(idB);
		};
		org.eclipse.dltk.internal.core.util.Util.sort(elements, comparer);
	}

	protected void assertSortedElementsEqual(String message, String expected,
			IModelElement[] elements) {
		sortElements(elements);
		assertElementsEqual(message, expected, elements);
	}

	protected void assertElementsEqual(String message, String expected,
			IModelElement[] elements) {
		assertElementsEqual(message, expected, elements,
				false/*
						 * don't show key
						 */);
	}

	protected void assertElementsEqual(String message, String expected,
			IModelElement[] elements, boolean showResolvedInfo) {
		StringBuffer buffer = new StringBuffer();
		if (elements != null) {
			for (int i = 0, length = elements.length; i < length; i++) {
				ModelElement element = (ModelElement) elements[i];
				if (element == null) {
					buffer.append("<null>");
				} else {
					buffer.append(
							element.toStringWithAncestors(showResolvedInfo));
				}
				if (i != length - 1)
					buffer.append("\n");
			}
		} else {
			buffer.append("<null>");
		}
		String actual = buffer.toString();
		if (!expected.equals(actual)) {
			if (this.displayName)
				System.out.println(getName() + " actual result is:");
			System.out.println(org.eclipse.dltk.core.tests.util.Util
					.displayString(actual, this.tabs) + this.endChar);
		}
		assertEquals(message, expected, actual);
	}

	protected void sortResources(Object[] resources) {
		Util.Comparer comparer = (a, b) -> {
			IResource resourceA = (IResource) a;
			IResource resourceB = (IResource) b;
			return resourceA.getFullPath().toString()
					.compareTo(resourceB.getFullPath().toString());
		};
		Util.sort(resources, comparer);
	}

	protected void assertResourceNamesEqual(String message, String expected,
			Object[] resources) {
		sortResources(resources);
		StringBuffer buffer = new StringBuffer();
		for (int i = 0, length = resources.length; i < length; i++) {
			IResource resource = (IResource) resources[i];
			buffer.append(resource == null ? "<null>" : resource.getName());
			if (i != length - 1)
				buffer.append("\n");
		}
		if (!expected.equals(buffer.toString())) {
			System.out.print(org.eclipse.dltk.core.tests.util.Util
					.displayString(buffer.toString(), 2));
			System.out.println(this.endChar);
		}
		assertEquals(message, expected, buffer.toString());
	}

	protected void assertDeltas(String message, String expected) {
		String actual = this.deltaListener.toString();
		if (!expected.equals(actual)) {
			System.out.println(actual);
		}
		assertEquals(message, expected, actual);
	}

	protected void assertDeltas(String message, String expected,
			IModelElementDelta delta) {
		String actual = delta == null ? "<null>" : delta.toString();
		if (!expected.equals(actual)) {
			System.out.println(actual);
		}
		assertEquals(message, expected, actual);
	}

	protected void assertMarkers(String message, String expectedMarkers,
			IScriptProject project) throws CoreException {
		IMarker[] markers = project.getProject().findMarkers(
				IScriptModelMarker.BUILDPATH_PROBLEM_MARKER, false,
				IResource.DEPTH_ZERO);
		sortMarkers(markers);
		assertMarkers(message, expectedMarkers, markers);
	}

	protected void assertMarkers(String message, String expectedMarkers,
			IMarker[] markers) throws CoreException {
		StringBuffer buffer = new StringBuffer();
		if (markers != null) {
			for (int i = 0, length = markers.length; i < length; i++) {
				IMarker marker = markers[i];
				buffer.append(marker.getAttribute(IMarker.MESSAGE));
				if (i != length - 1) {
					buffer.append("\n");
				}
			}
		}
		String actual = buffer.toString();
		if (!expectedMarkers.equals(actual)) {
			System.out.println(org.eclipse.dltk.core.tests.util.Util
					.displayString(actual, 2));
		}
		assertEquals(message, expectedMarkers, actual);
	}

	protected void sortMarkers(IMarker[] markers) {
		org.eclipse.dltk.internal.core.util.Util.Comparer comparer = (a, b) -> {
			IMarker markerA = (IMarker) a;
			IMarker markerB = (IMarker) b;
			return markerA.getAttribute(IMarker.MESSAGE, "") //$NON-NLS-1$
					.compareTo(markerB.getAttribute(IMarker.MESSAGE, "")); //$NON-NLS-1$
		};
		org.eclipse.dltk.internal.core.util.Util.sort(markers, comparer);
	}

	/**
	 * Sets the class path of the script project.
	 */
	public void setBuildpath(IScriptProject scriptProject,
			IBuildpathEntry[] buildpath) {
		try {
			scriptProject.setRawBuildpath(buildpath, null);
		} catch (ModelException e) {
			assertTrue("failed to set buildpath", false);
		}
	}

	/**
	 * Returns the last delta for the given element from the cached delta.
	 */
	protected IModelElementDelta getDeltaFor(IModelElement element) {
		return getDeltaFor(element, false);
	}

	/**
	 * Returns the delta for the given element from the cached delta. If the
	 * boolean is true returns the first delta found.
	 */
	protected IModelElementDelta getDeltaFor(IModelElement element,
			boolean returnFirst) {
		IModelElementDelta[] deltas = this.deltaListener.deltas;
		if (deltas == null)
			return null;
		IModelElementDelta result = null;
		for (int i = 0; i < deltas.length; i++) {
			IModelElementDelta delta = searchForDelta(element,
					this.deltaListener.deltas[i]);
			if (delta != null) {
				if (returnFirst) {
					return delta;
				}
				result = delta;
			}
		}
		return result;
	}

	/**
	 * Returns a delta for the given element in the delta tree
	 */
	protected IModelElementDelta searchForDelta(IModelElement element,
			IModelElementDelta delta) {

		if (delta == null) {
			return null;
		}
		if (delta.getElement().equals(element)) {
			return delta;
		}
		for (int i = 0; i < delta.getAffectedChildren().length; i++) {
			IModelElementDelta child = searchForDelta(element,
					delta.getAffectedChildren()[i]);
			if (child != null) {
				return child;
			}
		}
		return null;
	}

	/**
	 * Ensures the elements are present after creation.
	 */
	public void assertCreation(IModelElement[] newElements) {
		for (int i = 0; i < newElements.length; i++) {
			IModelElement newElement = newElements[i];
			assertTrue("Element should be present after creation",
					newElement.exists());
		}
	}

	/**
	 * Ensures the element is present after creation.
	 */
	public void assertCreation(IModelElement newElement) {
		assertCreation(new IModelElement[] { newElement });
	}

	/**
	 * Creates an operation to delete the given elements, asserts the operation
	 * is successful, and ensures the elements are no longer present in the
	 * model.
	 */
	public void assertDeletion(IModelElement[] elementsToDelete)
			throws ModelException {
		IModelElement elementToDelete = null;
		for (int i = 0; i < elementsToDelete.length; i++) {
			elementToDelete = elementsToDelete[i];
			assertTrue("Element must be present to be deleted",
					elementToDelete.exists());
		}

		getScriptModel().delete(elementsToDelete, false, null);

		for (int i = 0; i < elementsToDelete.length; i++) {
			elementToDelete = elementsToDelete[i];
			assertTrue("Element should not be present after deletion: "
					+ elementToDelete, !elementToDelete.exists());
		}
	}

	/**
	 * Returns the script Model this test suite is running on.
	 */
	public IScriptModel getScriptModel() {
		return DLTKCore.create(getWorkspaceRoot());
	}

	/**
	 * Wait for autobuild notification to occur
	 */
	public static void waitForAutoBuild() {
		WorkspaceAutoBuild.waitFor();
	}

	public void ensureCorrectPositioning(IParent container,
			IModelElement sibling, IModelElement positioned)
			throws ModelException {
		IModelElement[] children = container.getChildren();
		if (sibling != null) {
			// find the sibling
			boolean found = false;
			for (int i = 0; i < children.length; i++) {
				if (children[i].equals(sibling)) {
					assertTrue("element should be before sibling",
							i > 0 && children[i - 1].equals(positioned));
					found = true;
					break;
				}
			}
			assertTrue("Did not find sibling", found);
		}
	}

	public ISourceModule getWorkingCopy(String path, boolean computeProblems)
			throws ModelException {
		return getWorkingCopy(path, "", computeProblems);
	}

	public ISourceModule getWorkingCopy(String path, String source)
			throws ModelException {
		return getWorkingCopy(path, source, false);
	}

	public ISourceModule getWorkingCopy(String path, String source,
			boolean computeProblems) throws ModelException {
		if (this.wcOwner == null)
			this.wcOwner = new WorkingCopyOwner() {
			};
		return getWorkingCopy(path, source, this.wcOwner, computeProblems);
	}

	public ISourceModule getWorkingCopy(String path, String source,
			WorkingCopyOwner owner, boolean computeProblems)
			throws ModelException {
		IProblemRequestor problemRequestor = computeProblems
				? new IProblemRequestor() {
					@Override
					public void acceptProblem(IProblem problem) {
					}

					@Override
					public void beginReporting() {
					}

					@Override
					public void endReporting() {
					}

					@Override
					public boolean isActive() {
						return true;
					}
				}
				: null;
		return getWorkingCopy(path, source, owner, problemRequestor);
	}

	public ISourceModule getWorkingCopy(String path, String source,
			WorkingCopyOwner owner, IProblemRequestor problemRequestor)
			throws ModelException {
		ISourceModule workingCopy = getSourceModule(path);
		if (owner != null)
			workingCopy = workingCopy.getWorkingCopy(
					/* owner, problemRequestor, */null/*
														 * no progress monitor
														 */);
		else
			workingCopy.becomeWorkingCopy(problemRequestor,
					null/*
						 * no progress monitor
						 */);
		workingCopy.getBuffer().setContents(source);
		// if (problemRequestor instanceof ProblemRequestor)
		// ((ProblemRequestor)
		// problemRequestor).initialize(source.toCharArray());
		workingCopy.makeConsistent(null/* no progress monitor */);
		return workingCopy;
	}

	public static void waitUntilIndexesReady() {
		ModelManager.getModelManager().getIndexManager().waitUntilReady();
	}

	public static void storeFile(File dest, URL url) throws IOException {
		try (InputStream input = new BufferedInputStream(url.openStream());
				OutputStream output = new BufferedOutputStream(
						new FileOutputStream(dest))) {
			// Simple copy
			int ch = -1;
			while ((ch = input.read()) != -1) {
				output.write(ch);
			}
		}
	}

	public static File storeToMetadata(Bundle bundle, String name, String path)
			throws IOException {
		File pathFile = DLTKCore.getDefault().getStateLocation().append(name)
				.toFile();
		storeFile(pathFile, FileLocator.resolve(bundle.getEntry(path)));
		return pathFile;
	}
}
