/*******************************************************************************
 * Copyright (c) 2000, 2018 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.internal.ui.wizards.buildpath;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.BuildpathContainerInitializer;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IAccessRule;
import org.eclipse.dltk.core.IBuildpathAttribute;
import org.eclipse.dltk.core.IBuildpathContainer;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.ScriptModelUtil;
import org.eclipse.dltk.core.environment.EnvironmentManager;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.core.environment.IEnvironment;
import org.eclipse.dltk.core.environment.IFileHandle;
import org.eclipse.dltk.internal.core.BuildpathEntry;
import org.eclipse.dltk.launching.ScriptRuntime;
import org.eclipse.dltk.ui.DLTKUIPlugin;

public class BPListElement {

	public static final String EXCLUSION = "exclusion"; //$NON-NLS-1$

	public static final String INCLUSION = "inclusion"; //$NON-NLS-1$

	public static final String ACCESSRULES = "accessrules"; //$NON-NLS-1$

	public static final String COMBINE_ACCESSRULES = "combineaccessrules"; //$NON-NLS-1$

	public static final String NATIVE_LIB_PATH = ScriptRuntime.BUILDPATH_ATTR_LIBRARY_PATH_ENTRY;

	private IScriptProject fProject;

	private int fEntryKind;

	private IPath fPath, fOrginalPath;

	private IPath sourcePath, sourceRootPath;

	private IResource fResource;

	private boolean fIsExported;

	private boolean fExternal;

	private boolean fIsMissing;

	private Object fParentContainer;

	private IBuildpathEntry fCachedEntry;

	private ArrayList fChildren;

	private IPath fLinkTarget, fOrginalLinkTarget;

	private List fExtraAttributes = new ArrayList();

	public BPListElement(IScriptProject project, int entryKind, IPath path,
			IResource res, boolean external) {

		this(null, project, entryKind, path, res, external);
	}

	public BPListElement(Object parent, IScriptProject project, int entryKind,
			IPath path, IResource res, boolean external) {

		this(parent, project, entryKind, path, res, null, external);
	}

	public BPListElement(IScriptProject project, int entryKind,
			boolean external) {

		this(null, project, entryKind, null, null, external);
	}

	public BPListElement(Object parent, IScriptProject project, int entryKind,
			IPath path, IResource res, IPath linkTarget, boolean external) {

		fProject = project;

		fEntryKind = entryKind;
		fPath = path;
		fOrginalPath = path;
		fLinkTarget = linkTarget;
		fOrginalLinkTarget = linkTarget;
		fChildren = new ArrayList();
		fResource = res;
		fIsExported = false;

		fIsMissing = false;
		fCachedEntry = null;
		fParentContainer = parent;
		fExternal = external;

		switch (entryKind) {
		case IBuildpathEntry.BPE_SOURCE:
			createAttributeElement(INCLUSION, new Path[0], true);
			createAttributeElement(EXCLUSION, new Path[0], true);
			if (DLTKCore.DEBUG) {
				System.err.println(
						"TODO: Add adding containers for languages here"); //$NON-NLS-1$
				// createAttributeElement(NATIVE_LIB_PATH, null, false);
			}
			break;
		case IBuildpathEntry.BPE_LIBRARY:
			createAttributeElement(ACCESSRULES, new IAccessRule[0], true);
			break;
		case IBuildpathEntry.BPE_PROJECT:
			createAttributeElement(ACCESSRULES, new IAccessRule[0], true);
			createAttributeElement(COMBINE_ACCESSRULES, Boolean.FALSE, true); // not
			// rendered

			if (DLTKCore.DEBUG) {
				System.err.println(
						"TODO: Add adding containers for languages here"); //$NON-NLS-1$
				// createAttributeElement(NATIVE_LIB_PATH, null, false);
			}
			break;
		case IBuildpathEntry.BPE_CONTAINER:
			createAttributeElement(ACCESSRULES, new IAccessRule[0], true);
			try {
				IBuildpathContainer container = DLTKCore
						.getBuildpathContainer(fPath, fProject);
				if (container != null) {
					IBuildpathEntry[] entries = container.getBuildpathEntries();
					for (int i = 0; i < entries.length; i++) {
						IBuildpathEntry entry = entries[i];
						if (entry != null) {
							BPListElement curr = createFromExisting(this, entry,
									fProject);
							fChildren.add(curr);
						} else {
							DLTKUIPlugin.logErrorMessage(
									"Null entry in container '" + fPath + "'"); //$NON-NLS-1$//$NON-NLS-2$
						}
					}
				}
			} catch (ModelException e) {
			}
			// createAttributeElement( NATIVE_LIB_PATH, null, false );
			if (DLTKCore.DEBUG) {
				System.err.println(
						"TODO: Add adding containers for languages here"); //$NON-NLS-1$
				// createAttributeElement(NATIVE_LIB_PATH, null, false);
			}
			break;
		default:
		}

	}

	public IBuildpathEntry getBuildpathEntry() {

		if (fCachedEntry == null) {
			fCachedEntry = newBuildpathEntry();
			fCachedEntry.setSourceAttachmentPath(getSourcePath());
			fCachedEntry.setSourceAttachmentRootPath(getSourceRootPath());
		}
		return fCachedEntry;
	}

	private IBuildpathAttribute[] getBuildpathAttributes() {

		ArrayList<IBuildpathAttribute> res = new ArrayList<>();
		for (int i = 0; i < fChildren.size(); i++) {
			Object curr = fChildren.get(i);
			if (curr instanceof BPListElementAttribute) {
				BPListElementAttribute elem = (BPListElementAttribute) curr;
				if (!elem.isBuiltIn() && elem.getValue() != null) {
					res.add(elem.newBuildpathAttribute());
				}
			}
		}
		res.addAll(this.fExtraAttributes);
		return res.toArray(new IBuildpathAttribute[res.size()]);
	}

	private IBuildpathEntry newBuildpathEntry() {

		IBuildpathAttribute[] extraAttributes = getBuildpathAttributes();
		switch (fEntryKind) {
		case IBuildpathEntry.BPE_SOURCE:
			IPath[] inclusionPattern = (IPath[]) getAttribute(INCLUSION);
			IPath[] exclusionPattern = (IPath[]) getAttribute(EXCLUSION);
			return DLTKCore.newSourceEntry(fPath, inclusionPattern,
					exclusionPattern, extraAttributes);
		case IBuildpathEntry.BPE_LIBRARY: {
			IAccessRule[] accesRules = (IAccessRule[]) getAttribute(
					ACCESSRULES);
			if (fPath.toString()
					.startsWith(IBuildpathEntry.BUILTIN_EXTERNAL_ENTRY_STR)) {
				return DLTKCore.newBuiltinEntry(fPath, accesRules,
						extraAttributes, new IPath[0],
						BuildpathEntry.INCLUDE_ALL, isExported(), fExternal);
			}
			return DLTKCore.newLibraryEntry(fPath, accesRules, extraAttributes,
					isExported(), fExternal);
		}
		case IBuildpathEntry.BPE_PROJECT: {
			IAccessRule[] accesRules = (IAccessRule[]) getAttribute(
					ACCESSRULES);
			boolean combineAccessRules = ((Boolean) getAttribute(
					COMBINE_ACCESSRULES)).booleanValue();
			return DLTKCore.newProjectEntry(fPath, accesRules,
					combineAccessRules, extraAttributes, isExported());
		}
		case IBuildpathEntry.BPE_CONTAINER: {
			IAccessRule[] accesRules = (IAccessRule[]) getAttribute(
					ACCESSRULES);
			return DLTKCore.newContainerEntry(fPath, accesRules,
					extraAttributes, isExported());
		}
		default:
			return null;
		}
	}

	/**
	 * Gets the class path entry path.
	 *
	 * @see IBuildpathEntry#getPath()
	 */
	public IPath getPath() {

		return fPath;
	}

	public IPath getSourcePath() {
		return sourcePath;
	}

	public IPath getSourceRootPath() {
		return sourceRootPath;
	}

	public void setSourcePath(IPath sourcePath) {
		this.sourcePath = sourcePath;
	}

	public void setSourceRootPath(IPath sourceRootPath) {
		this.sourceRootPath = sourceRootPath;
	}

	/**
	 * Gets the class path entry kind.
	 *
	 * @see IBuildpathEntry#getEntryKind()
	 */
	public int getEntryKind() {

		return fEntryKind;
	}

	/**
	 * Entries without resource are either non existing or a variable entry
	 * External archives do not have a resource
	 */
	public IResource getResource() {

		return fResource;
	}

	public BPListElementAttribute setAttribute(String key, Object value) {

		BPListElementAttribute attribute = findAttributeElement(key);
		if (attribute == null) {
			// BPListElementAttribute attr = new BPListElementAttribute(this,
			// key,
			// value, true);
			// fChildren.add(attr);
			return null;
		}
		if (key.equals(EXCLUSION) || key.equals(INCLUSION)) {
			Assert.isTrue(
					value != null || fEntryKind != IBuildpathEntry.BPE_SOURCE);
		}

		if (key.equals(ACCESSRULES)) {
			Assert.isTrue(
					value != null || fEntryKind == IBuildpathEntry.BPE_SOURCE);
		}
		if (key.equals(COMBINE_ACCESSRULES)) {
			Assert.isTrue(value instanceof Boolean);
		}

		attribute.setValue(value);
		attributeChanged(key);
		return attribute;
	}

	public boolean addToExclusions(IPath path) {

		String key = BPListElement.EXCLUSION;
		return addFilter(path, key);
	}

	public boolean addToInclusion(IPath path) {

		String key = BPListElement.INCLUSION;
		return addFilter(path, key);
	}

	public boolean removeFromExclusions(IPath path) {

		String key = BPListElement.EXCLUSION;
		return removeFilter(path, key);
	}

	public boolean removeFromInclusion(IPath path) {

		String key = BPListElement.INCLUSION;
		return removeFilter(path, key);
	}

	private boolean addFilter(IPath path, String key) {

		IPath[] exclusionFilters = (IPath[]) getAttribute(key);
		if (!ScriptModelUtil.isExcludedPath(path, exclusionFilters)) {
			IPath pathToExclude = path
					.removeFirstSegments(getPath().segmentCount())
					.addTrailingSeparator();
			IPath[] newExclusionFilters = new IPath[exclusionFilters.length
					+ 1];
			System.arraycopy(exclusionFilters, 0, newExclusionFilters, 0,
					exclusionFilters.length);
			newExclusionFilters[exclusionFilters.length] = pathToExclude;
			setAttribute(key, newExclusionFilters);
			return true;
		}
		return false;
	}

	private boolean removeFilter(IPath path, String key) {

		IPath[] exclusionFilters = (IPath[]) getAttribute(key);
		IPath pathToExclude = path.removeFirstSegments(getPath().segmentCount())
				.addTrailingSeparator();
		if (ScriptModelUtil.isExcludedPath(pathToExclude, exclusionFilters)) {

			List<IPath> l = new ArrayList<>(Arrays.asList(exclusionFilters));
			l.remove(pathToExclude);
			IPath[] newExclusionFilters = l.toArray(new IPath[l.size()]);
			setAttribute(key, newExclusionFilters);
			return true;
		}
		return false;
	}

	public BPListElementAttribute findAttributeElement(String key) {

		for (int i = 0; i < fChildren.size(); i++) {
			Object curr = fChildren.get(i);
			if (curr instanceof BPListElementAttribute) {
				BPListElementAttribute elem = (BPListElementAttribute) curr;
				if (key.equals(elem.getKey())) {
					return elem;
				}
			}
		}
		return null;
	}

	public Object getAttribute(String key) {

		BPListElementAttribute attrib = findAttributeElement(key);
		if (attrib != null) {
			return attrib.getValue();
		}
		return null;
	}

	private void createAttributeElement(String key, Object value,
			boolean builtIn) {

		fChildren.add(new BPListElementAttribute(this, key, value, builtIn));
	}

	private static boolean isFiltered(Object entry, String[] filteredKeys) {

		if (entry instanceof BPListElementAttribute) {
			String key = ((BPListElementAttribute) entry).getKey();
			for (int i = 0; i < filteredKeys.length; i++) {
				if (key.equals(filteredKeys[i])) {
					return true;
				}
			}
		}
		return false;
	}

	private Object[] getFilteredChildren(String[] filteredKeys) {

		int nChildren = fChildren.size();
		ArrayList res = new ArrayList(nChildren);

		for (int i = 0; i < nChildren; i++) {
			Object curr = fChildren.get(i);
			if (!isFiltered(curr, filteredKeys)) {
				res.add(curr);
			}
		}
		return res.toArray();
	}

	public Object[] getChildren() {

		if (fParentContainer instanceof BPListElement) {
			if (DLTKCore.DEBUG) {
				System.err
						.println("TODO:Add navive library containers support"); //$NON-NLS-1$
			}
			// IPath InterpreterEnvironmentContainerPath = new Path(
			// ScriptRuntime.InterpreterEnvironment_CONTAINER );
			// if( InterpreterEnvironmentContainerPath.isPrefixOf( ( (
			// CPListElement )fParentContainer ).getPath( ) ) ) {
			// // don't show access rules and native path for containers (bug
			// 98710)
			// return getFilteredChildren( new String [] { ACCESSRULES,
			// COMBINE_ACCESSRULES, NATIVE_LIB_PATH } );
			// }
		}
		if (fEntryKind == IBuildpathEntry.BPE_PROJECT) {
			return getFilteredChildren(new String[] { COMBINE_ACCESSRULES });
		}
		return fChildren.toArray();
	}

	public Object getParentContainer() {

		return fParentContainer;
	}

	public void setParentContainer(Object parent) {
		fParentContainer = parent;
	}

	private void attributeChanged(String key) {

		fCachedEntry = null;
	}

	private boolean canUpdateContainer() {

		if (fEntryKind == IBuildpathEntry.BPE_CONTAINER && fProject != null) {
			BuildpathContainerInitializer initializer = DLTKCore
					.getBuildpathContainerInitializer(fPath.segment(0));
			return (initializer != null && initializer
					.canUpdateBuildpathContainer(fPath, fProject));
		}
		return false;
	}

	public boolean isInNonModifiableContainer() {

		if (fParentContainer instanceof BPListElement) {
			return !((BPListElement) fParentContainer).canUpdateContainer();
		}
		return false;
	}

	@Override
	public boolean equals(Object other) {

		if (other != null && other.getClass().equals(getClass())) {
			BPListElement elem = (BPListElement) other;
			// check extra attributes
			if (this.fExtraAttributes.size() != elem.fExtraAttributes.size()) {
				Set ns = new HashSet();
				ns.addAll(this.fExtraAttributes);
				ns.removeAll(elem.fExtraAttributes);
				if (ns.size() > 0) {
					return false;
				}
			}
			return getBuildpathEntry().equals(elem.getBuildpathEntry());
		}
		return false;
	}

	@Override
	public int hashCode() {

		return fPath.hashCode() + fEntryKind;
	}

	@Override
	public String toString() {

		return getBuildpathEntry().toString();
	}

	/**
	 * Returns if a entry is missing.
	 *
	 * @return Returns a boolean
	 */
	public boolean isMissing() {

		return fIsMissing;
	}

	/**
	 * Sets the 'missing' state of the entry.
	 */
	public void setIsMissing(boolean isMissing) {

		fIsMissing = isMissing;
	}

	/**
	 * Returns if a entry is exported (only applies to libraries)
	 *
	 * @return Returns a boolean
	 */
	public boolean isExported() {

		return fIsExported;
	}

	/**
	 * Sets the export state of the entry.
	 */
	public void setExported(boolean isExported) {

		if (isExported != fIsExported) {
			fIsExported = isExported;

			attributeChanged(null);
		}
	}

	/**
	 * Gets the project.
	 *
	 * @return Returns a IScriptProject
	 */
	public IScriptProject getScriptProject() {

		return fProject;
	}

	public static BPListElement createFromExisting(IBuildpathEntry curr,
			IScriptProject project) {

		return createFromExisting(null, curr, project);
	}

	public static BPListElement createFromExisting(Object parent,
			IBuildpathEntry curr, IScriptProject project) {

		IPath path = curr.getPath();
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

		// get the resource
		IResource res = null;
		boolean isMissing = false;
		IPath linkTarget = null;
		boolean isExternel = false;

		switch (curr.getEntryKind()) {
		case IBuildpathEntry.BPE_CONTAINER:
			try {
				isMissing = project != null && (DLTKCore
						.getBuildpathContainer(path, project) == null);
			} catch (ModelException e) {
				isMissing = true;
			}
			break;
		case IBuildpathEntry.BPE_LIBRARY:
			res = root.findMember(path);
			isExternel = curr.isExternal();
			if (res == null) {
				if (!ArchiveFileFilter.isArchivePath(path)) {
					if (root.getWorkspace()
							.validatePath(path.toString(), IResource.FOLDER)
							.isOK()
							&& root.getProject(path.segment(0)).exists()) {
						res = root.getFolder(path);
					}
				}
				if (path.toString().startsWith(
						IBuildpathEntry.BUILTIN_EXTERNAL_ENTRY_STR)) {
					isMissing = false;
				} else {
					IEnvironment environment = EnvironmentManager
							.getEnvironment(project);
					IFileHandle handle = EnvironmentPathUtils
							.getFile(environment, path);
					if (handle == null || !handle.exists()) {
						isMissing = true;
					}
				}
			} else if (res.isLinked()) {
				linkTarget = res.getLocation();
			}
			break;
		case IBuildpathEntry.BPE_SOURCE:
			path = path.removeTrailingSeparator();
			res = root.findMember(path);
			if (res == null) {
				if (root.getWorkspace()
						.validatePath(path.toString(), IResource.FOLDER)
						.isOK()) {
					res = root.getFolder(path);
				}
				isMissing = true;
			} else if (res.isLinked()) {
				linkTarget = res.getLocation();
			}
			break;
		case IBuildpathEntry.BPE_PROJECT:
			res = root.findMember(path);
			isMissing = (res == null);
			break;
		}
		BPListElement elem = new BPListElement(parent, project,
				curr.getEntryKind(), path, res, linkTarget, isExternel);
		elem.setExported(curr.isExported());
		elem.setAttribute(EXCLUSION, curr.getExclusionPatterns());
		elem.setAttribute(INCLUSION, curr.getInclusionPatterns());
		elem.setAttribute(ACCESSRULES, curr.getAccessRules());
		elem.setAttribute(COMBINE_ACCESSRULES, curr.combineAccessRules());
		elem.setSourcePath(curr.getSourceAttachmentPath());
		elem.setSourceRootPath(curr.getSourceAttachmentRootPath());

		IBuildpathAttribute[] extraAttributes = curr.getExtraAttributes();
		for (int i = 0; i < extraAttributes.length; i++) {
			IBuildpathAttribute attrib = extraAttributes[i];
			if (elem.setAttribute(attrib.getName(),
					attrib.getValue()) == null) {
				// Store this in extraAttributesList
				elem.fExtraAttributes.add(attrib);
			}
		}

		if (project != null && project.exists()) {
			elem.setIsMissing(isMissing);
		}
		return elem;
	}

	public static StringBuffer appendEncodePath(IPath path, StringBuffer buf) {

		if (path != null) {
			String str = path.toString();
			buf.append('[').append(str.length()).append(']').append(str);
		} else {
			buf.append('[').append(']');
		}
		return buf;
	}

	public static StringBuffer appendEncodedString(String str,
			StringBuffer buf) {

		if (str != null) {
			buf.append('[').append(str.length()).append(']').append(str);
		} else {
			buf.append('[').append(']');
		}
		return buf;
	}

	public static StringBuffer appendEncodedFilter(IPath[] filters,
			StringBuffer buf) {

		if (filters != null) {
			buf.append('[').append(filters.length).append(']');
			for (int i = 0; i < filters.length; i++) {
				appendEncodePath(filters[i], buf).append(';');
			}
		} else {
			buf.append('[').append(']');
		}
		return buf;
	}

	public static StringBuffer appendEncodedAccessRules(IAccessRule[] rules,
			StringBuffer buf) {

		if (rules != null) {
			buf.append('[').append(rules.length).append(']');
			for (int i = 0; i < rules.length; i++) {
				appendEncodePath(rules[i].getPattern(), buf).append(';');
				buf.append(rules[i].getKind()).append(';');
			}
		} else {
			buf.append('[').append(']');
		}
		return buf;
	}

	public StringBuffer appendEncodedSettings(StringBuffer buf) {

		buf.append(fEntryKind).append(';');
		if (getLinkTarget() == null) {
			appendEncodePath(fPath, buf).append(';');
		} else {
			appendEncodePath(fPath, buf).append('-').append('>');
			appendEncodePath(getLinkTarget(), buf).append(';');
		}
		buf.append(Boolean.valueOf(fIsExported)).append(';');
		for (int i = 0; i < fChildren.size(); i++) {
			Object curr = fChildren.get(i);
			if (curr instanceof BPListElementAttribute) {
				BPListElementAttribute elem = (BPListElementAttribute) curr;
				if (elem.isBuiltIn()) {
					String key = elem.getKey();
					if (EXCLUSION.equals(key) || INCLUSION.equals(key)) {
						appendEncodedFilter((IPath[]) elem.getValue(), buf)
								.append(';');
					} else if (ACCESSRULES.equals(key)) {
						appendEncodedAccessRules(
								(IAccessRule[]) elem.getValue(), buf)
										.append(';');
					} else if (COMBINE_ACCESSRULES.equals(key)) {
						buf.append(((Boolean) elem.getValue()).booleanValue())
								.append(';');
					}
				} else {
					appendEncodedString((String) elem.getValue(), buf);
				}
			}
		}
		// Add fExtraAttributeChanges
		for (Iterator iterator = this.fExtraAttributes.iterator(); iterator
				.hasNext();) {
			IBuildpathAttribute attr = (IBuildpathAttribute) iterator.next();
			appendEncodedString("attr:" + attr.getName() + ":val" //$NON-NLS-1$ //$NON-NLS-2$
					+ attr.getValue() + ";", buf); //$NON-NLS-1$
		}
		return buf;
	}

	public IPath getLinkTarget() {

		return fLinkTarget;
	}

	public void setPath(IPath path) {

		fCachedEntry = null;
		fPath = path;
	}

	public void setLinkTarget(IPath linkTarget) {

		fCachedEntry = null;
		fLinkTarget = linkTarget;
	}

	public static void insert(BPListElement element,
			List<BPListElement> cpList) {

		int length = cpList.size();
		BPListElement[] elements = cpList.toArray(new BPListElement[length]);
		int i = 0;
		while (i < length
				&& elements[i].getEntryKind() != element.getEntryKind()) {
			i++;
		}
		if (i < length) {
			i++;
			while (i < length
					&& elements[i].getEntryKind() == element.getEntryKind()) {
				i++;
			}
			cpList.add(i, element);
			return;
		}

		switch (element.getEntryKind()) {
		case IBuildpathEntry.BPE_SOURCE:
			cpList.add(0, element);
			break;
		case IBuildpathEntry.BPE_CONTAINER:
		case IBuildpathEntry.BPE_LIBRARY:
		case IBuildpathEntry.BPE_PROJECT:
		default:
			cpList.add(element);
			break;
		}
	}

	public static IBuildpathEntry[] convertToBuildpathEntries(
			List/*
				 * <CPListElement >
				 */ cpList) {

		IBuildpathEntry[] result = new IBuildpathEntry[cpList.size()];
		int i = 0;
		for (Iterator iter = cpList.iterator(); iter.hasNext();) {
			BPListElement cur = (BPListElement) iter.next();
			result[i] = cur.getBuildpathEntry();
			i++;
		}
		return result;
	}

	public static BPListElement[] createFromExisting(IScriptProject project)
			throws ModelException {

		IBuildpathEntry[] rawBuildpath = project.getRawBuildpath();
		BPListElement[] result = new BPListElement[rawBuildpath.length];
		for (int i = 0; i < rawBuildpath.length; i++) {
			result[i] = BPListElement.createFromExisting(rawBuildpath[i],
					project);
		}
		return result;
	}

	public static boolean isProjectSourceFolder(BPListElement[] existing,
			IScriptProject project) {

		IPath projPath = project.getProject().getFullPath();
		for (int i = 0; i < existing.length; i++) {
			IBuildpathEntry curr = existing[i].getBuildpathEntry();
			if (curr.getEntryKind() == IBuildpathEntry.BPE_SOURCE) {
				if (projPath.equals(curr.getPath())) {
					return true;
				}
			}
		}
		return false;
	}

	public IPath getOrginalPath() {

		return fOrginalPath;
	}

	public IPath getOrginalLinkTarget() {

		return fOrginalLinkTarget;
	}

	public boolean isExternalFolder() {
		return this.fExternal && this.fEntryKind == IBuildpathEntry.BPE_LIBRARY
				&& !Util.isArchiveFileName(DLTKLanguageManager
						.getLanguageToolkit(getScriptProject()),
						this.fPath.toOSString());
	}

}
