/*******************************************************************************
 * Copyright (c) 2000, 2007 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Matt Chapman, mpchapman@gmail.com - 89977 Make JDT .java agnostic
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.buildpath;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatus;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.PreferenceConstants;

import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ArchiveFileFilter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.newsourcepage.ClasspathModifierQueries.OutputFolderValidator;

public class ClasspathModifier {

	private ClasspathModifier() {}
	
	public static BuildpathDelta setOutputLocation(CPListElement elementToChange, IPath outputPath, boolean allowInvalidCP, CPJavaProject cpProject) throws CoreException {
		BuildpathDelta result= new BuildpathDelta(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_EditOutput_tooltip);
		
		IJavaProject javaProject= cpProject.getJavaProject();
		IProject project= javaProject.getProject();
		IWorkspace workspace= project.getWorkspace();
		
		IPath projectPath= project.getFullPath();								
		
		if (!allowInvalidCP && cpProject.getDefaultOutputLocation().segmentCount() == 1 && !projectPath.equals(elementToChange.getPath())) {
			String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
			cpProject.setDefaultOutputLocation(cpProject.getDefaultOutputLocation().append(outputFolderName));
			List existingEntries= cpProject.getCPListElements();
			CPListElement elem= ClasspathModifier.getListElement(javaProject.getPath(), existingEntries);
            if (elem != null) {
            	existingEntries.remove(elem);
            	result.removeEntry(elem);
            }
		}
		
		if (outputPath != null)
			exclude(outputPath, cpProject.getCPListElements(), new ArrayList(), cpProject.getJavaProject(), null);
		
		IPath oldOutputLocation= (IPath)elementToChange.getAttribute(CPListElement.OUTPUT);
        if (oldOutputLocation != null && oldOutputLocation.segmentCount() > 1 && !oldOutputLocation.equals(cpProject.getDefaultOutputLocation())) {
			include(cpProject, oldOutputLocation);
        	result.addDeletedResource(workspace.getRoot().getFolder(oldOutputLocation));
        }
		elementToChange.setAttribute(CPListElement.OUTPUT, outputPath);
		
		result.setDefaultOutputLocation(cpProject.getDefaultOutputLocation());
		result.setNewEntries((CPListElement[])cpProject.getCPListElements().toArray(new CPListElement[cpProject.getCPListElements().size()]));
		if (outputPath != null && outputPath.segmentCount() > 1) {
			result.addCreatedResource(workspace.getRoot().getFolder(outputPath));
		}
		
		return result;
	}

	public static IStatus checkSetOutputLocationPrecondition(CPListElement elementToChange, IPath outputPath, boolean allowInvalidCP, CPJavaProject cpProject) throws CoreException {
		IJavaProject javaProject= cpProject.getJavaProject();
		IProject project= javaProject.getProject();
		IWorkspace workspace= project.getWorkspace();
		
		IPath projectPath= project.getFullPath();		
		
		if (outputPath == null)
			outputPath= cpProject.getDefaultOutputLocation();
						
		IStatus pathValidation= workspace.validatePath(outputPath.toString(), IResource.PROJECT | IResource.FOLDER);
		if (!pathValidation.isOK())
			return new StatusInfo(IStatus.ERROR, Messages.format(NewWizardMessages.OutputLocationDialog_error_invalidpath, pathValidation.getMessage()));
		
		IWorkspaceRoot root= workspace.getRoot();
		IResource res= root.findMember(outputPath);
		if (res != null) {
			// if exists, must be a folder or project
			if (res.getType() == IResource.FILE)
				return new StatusInfo(IStatus.ERROR, NewWizardMessages.OutputLocationDialog_error_existingisfile);
		}
		
		IStatus result= StatusInfo.OK_STATUS;
		
		int index= cpProject.indexOf(elementToChange);
		cpProject= cpProject.createWorkingCopy();
		elementToChange= cpProject.get(index);		
		
		if (!allowInvalidCP && cpProject.getDefaultOutputLocation().segmentCount() == 1 && !projectPath.equals(elementToChange.getPath())) {
			String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
			cpProject.setDefaultOutputLocation(cpProject.getDefaultOutputLocation().append(outputFolderName));
			ClasspathModifier.removeFromClasspath(javaProject, cpProject.getCPListElements(), null);
			result= new StatusInfo(IStatus.INFO, Messages.format(NewWizardMessages.OutputLocationDialog_removeProjectFromBP, cpProject.getDefaultOutputLocation()));
		}
		
		exclude(outputPath, cpProject.getCPListElements(), new ArrayList(), cpProject.getJavaProject(), null);
        
		IPath oldOutputLocation= (IPath)elementToChange.getAttribute(CPListElement.OUTPUT);
        if (oldOutputLocation != null && oldOutputLocation.segmentCount() > 1 && !oldOutputLocation.equals(cpProject.getDefaultOutputLocation())) {
			include(cpProject, oldOutputLocation);
        }
		elementToChange.setAttribute(CPListElement.OUTPUT, outputPath);
		
		IJavaModelStatus status= JavaConventions.validateClasspath(javaProject, cpProject.getClasspathEntries(), cpProject.getDefaultOutputLocation());
		if (!status.isOK()) {
			if (allowInvalidCP) {
				return new StatusInfo(IStatus.WARNING, status.getMessage());
			} else {
				return new StatusInfo(IStatus.ERROR, status.getMessage());
			}
		}
		
		if (outputPath.segmentCount() - projectPath.segmentCount() < 1)
			return result;
		
		String lastSegment= outputPath.lastSegment();
		if (lastSegment == null)
			return result;
		
		if (lastSegment.equals(".settings") && outputPath.segmentCount() - projectPath.segmentCount() == 1) { //$NON-NLS-1$

			StatusInfo statusInfo= new StatusInfo(IStatus.WARNING, NewWizardMessages.OutputLocation_SettingsAsLocation);
			if (result.isOK()) {
				return statusInfo;
			} else {
				MultiStatus ms= new MultiStatus(result.getPlugin(), result.getCode(), new IStatus[] {result, statusInfo}, statusInfo.getMessage(), null);
				return ms;
			}
		}
		
		if (lastSegment.length() > 1 && lastSegment.charAt(0) == '.') {
			StatusInfo statusInfo= new StatusInfo(IStatus.WARNING, Messages.format(NewWizardMessages.OutputLocation_DotAsLocation, outputPath.toString()));
			if (result.isOK()) {
				return statusInfo;
			} else {
				MultiStatus ms= new MultiStatus(result.getPlugin(), result.getCode(), new IStatus[] {result, statusInfo}, statusInfo.getMessage(), null);
				return ms;
			}
		}
		
		return result;
	}
	
    public static IStatus checkAddExternalJarsPrecondition(IPath[] absolutePaths, CPJavaProject cpProject) throws CoreException {
    	IStatus result= StatusInfo.OK_STATUS;
    	
    	IJavaProject javaProject= cpProject.getJavaProject();
    	
    	List newEntries= new ArrayList();
    	List duplicateEntries= new ArrayList();
    	List existingEntries= cpProject.getCPListElements();
    	for (int i= 0; i < absolutePaths.length; i++) {
	        CPListElement newEntry= new CPListElement(javaProject, IClasspathEntry.CPE_LIBRARY, absolutePaths[i], null);
	        if (existingEntries.contains(newEntry)) {
	        	duplicateEntries.add(newEntry);
	        } else {
	        	newEntries.add(newEntry);
	        }
        }
    	
		if (duplicateEntries.size() > 0) {
			String message;
			if (duplicateEntries.size() > 1) {
				StringBuffer buf= new StringBuffer();
				for (Iterator iterator= duplicateEntries.iterator(); iterator.hasNext();) {
	                CPListElement dup= (CPListElement)iterator.next();
	                buf.append('\n').append(dup.getPath().lastSegment());
                }
				message= Messages.format(NewWizardMessages.AddArchiveToBuildpathAction_DuplicateArchivesInfo_message, buf.toString());
			} else {
				message= Messages.format(NewWizardMessages.AddArchiveToBuildpathAction_DuplicateArchiveInfo_message, ((CPListElement)duplicateEntries.get(0)).getPath().lastSegment());
			}
			result= new StatusInfo(IStatus.INFO, message);
		}
		
		if (newEntries.size() == 0)
			return result;
		
		cpProject= cpProject.createWorkingCopy();
		existingEntries= cpProject.getCPListElements();
	
		for (Iterator iterator= newEntries.iterator(); iterator.hasNext();) {
            CPListElement newEntry= (CPListElement)iterator.next();
            insertAtEndOfCategory(newEntry, existingEntries);
        }
		
		IJavaModelStatus cpStatus= JavaConventions.validateClasspath(javaProject, cpProject.getClasspathEntries(), cpProject.getDefaultOutputLocation());
		if (!cpStatus.isOK())
			return cpStatus;
		
		return result;
    }
    
    public static BuildpathDelta addExternalJars(IPath[] absolutePaths, CPJavaProject cpProject) throws CoreException {
    	BuildpathDelta result= new BuildpathDelta(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_AddJarCP_tooltip);
    	
    	IJavaProject javaProject= cpProject.getJavaProject();
    	
    	List existingEntries= cpProject.getCPListElements();
    	for (int i= 0; i < absolutePaths.length; i++) {
	        CPListElement newEntry= new CPListElement(javaProject, IClasspathEntry.CPE_LIBRARY, absolutePaths[i], null);
	        if (!existingEntries.contains(newEntry)) {
	        	insertAtEndOfCategory(newEntry, existingEntries);
	        	result.addEntry(newEntry);
	        }
        }
    	
		result.setNewEntries((CPListElement[])existingEntries.toArray(new CPListElement[existingEntries.size()]));
		result.setDefaultOutputLocation(cpProject.getDefaultOutputLocation());
		return result;
    }
    
    public static BuildpathDelta removeFromBuildpath(CPListElement[] toRemove, CPJavaProject cpProject) {
    	
        IJavaProject javaProject= cpProject.getJavaProject();
		IPath projectPath= javaProject.getPath();
        IWorkspaceRoot workspaceRoot= javaProject.getProject().getWorkspace().getRoot();
        
    	List existingEntries= cpProject.getCPListElements();
		BuildpathDelta result= new BuildpathDelta(NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_RemoveFromCP_tooltip);
		
		for (int i= 0; i < toRemove.length; i++) {
	        CPListElement element= toRemove[i];
	        existingEntries.remove(element);
	        result.removeEntry(element);
	        IPath path= element.getPath();
			removeFilters(path, javaProject, existingEntries);
			if (!path.equals(projectPath)) {
	            IResource member= workspaceRoot.findMember(path);
	            if (member != null)
	            	result.addDeletedResource(member);
            } else if (cpProject.getDefaultOutputLocation().equals(projectPath) && containsSourceFolders(cpProject)) {
            	String outputFolderName= PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME);
    			cpProject.setDefaultOutputLocation(cpProject.getDefaultOutputLocation().append(outputFolderName));
            }
        }
		
		result.setDefaultOutputLocation(cpProject.getDefaultOutputLocation());
    	result.setNewEntries((CPListElement[])existingEntries.toArray(new CPListElement[existingEntries.size()]));

	    return result;
    }
    
    private static boolean containsSourceFolders(CPJavaProject cpProject) {
    	List elements= cpProject.getCPListElements();
    	for (Iterator iterator= elements.iterator(); iterator.hasNext();) {
	        CPListElement element= (CPListElement)iterator.next();
	        if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE)
	        	return true;
        }
	    return false;
    }

	private static void include(CPJavaProject cpProject, IPath path) {
	    List elements= cpProject.getCPListElements();
	    for (Iterator iterator= elements.iterator(); iterator.hasNext();) {
	        CPListElement element= (CPListElement)iterator.next();
	        element.removeFromExclusions(path);
	    }
    }

	/**
	 * Get the <code>IClasspathEntry</code> from the project and 
	 * convert it into a list of <code>CPListElement</code>s.
	 * 
	 * @param project the Java project to get it's build path entries from
	 * @return a list of <code>CPListElement</code>s corresponding to the 
	 * build path entries of the project
	 * @throws JavaModelException
	 */
	public static List getExistingEntries(IJavaProject project) throws JavaModelException {
		IClasspathEntry[] classpathEntries= project.getRawClasspath();
		ArrayList newClassPath= new ArrayList();
		for (int i= 0; i < classpathEntries.length; i++) {
			IClasspathEntry curr= classpathEntries[i];
			newClassPath.add(CPListElement.createFromExisting(curr, project));
		}
		return newClassPath;
	}

	/**
	 * Try to find the corresponding and modified <code>CPListElement</code> for the root 
	 * in the list of elements and return it.
	 * If no one can be found, the roots <code>ClasspathEntry</code> is converted to a 
	 * <code>CPListElement</code> and returned.
	 * 
	 * @param elements a list of <code>CPListElements</code>
	 * @param root the root to find the <code>ClasspathEntry</code> for represented by 
	 * a <code>CPListElement</code>
	 * @return the <code>CPListElement</code> found in the list (matching by using the path) or 
	 * the roots own <code>IClasspathEntry</code> converted to a <code>CPListElement</code>.
	 * @throws JavaModelException
	 */
	public static CPListElement getClasspathEntry(List elements, IPackageFragmentRoot root) throws JavaModelException {
		IClasspathEntry entry= root.getRawClasspathEntry();
		for (int i= 0; i < elements.size(); i++) {
			CPListElement element= (CPListElement) elements.get(i);
			if (element.getPath().equals(root.getPath()) && element.getEntryKind() == entry.getEntryKind())
				return (CPListElement) elements.get(i);
		}
		CPListElement newElement= CPListElement.createFromExisting(entry, root.getJavaProject());
		elements.add(newElement);
		return newElement;
	}

	/**
	 * For a given <code>IResource</code>, try to
	 * convert it into a <code>IPackageFragmentRoot</code>
	 * if possible or return <code>null</code> if no
	 * fragment root could be created.
	 * 
	 * @param resource the resource to be converted
	 * @return the <code>resource<code> as
	 * <code>IPackageFragment</code>,or <code>null</code>
	 * if failed to convert
	 */
	public static IPackageFragment getFragment(IResource resource) {
		IJavaElement elem= JavaCore.create(resource);
		if (elem instanceof IPackageFragment)
			return (IPackageFragment) elem;
		return null;
	}

	/**
	 * Get the source folder of a given <code>IResource</code> element,
	 * starting with the resource's parent.
	 * 
	 * @param resource the resource to get the fragment root from
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return resolved fragment root, or <code>null</code> the resource is not (in) a source folder
	 * @throws JavaModelException
	 */
	public static IPackageFragmentRoot getFragmentRoot(IResource resource, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		IJavaElement javaElem= null;
		if (resource.getFullPath().equals(project.getPath()))
			return project.getPackageFragmentRoot(resource);
		IContainer container= resource.getParent();
		do {
			if (container instanceof IFolder)
				javaElem= JavaCore.create((IFolder) container);
			if (container.getFullPath().equals(project.getPath())) {
				javaElem= project;
				break;
			}
			container= container.getParent();
			if (container == null)
				return null;
		} while (javaElem == null || !(javaElem instanceof IPackageFragmentRoot));
		if (javaElem instanceof IJavaProject) {
			if (!isSourceFolder((IJavaProject)javaElem))
				return null;
			javaElem= project.getPackageFragmentRoot(project.getResource());
		}
		return (IPackageFragmentRoot) javaElem;
	}

	/**
	 * Get the <code>IClasspathEntry</code> for the
	 * given path by looking up all
	 * build path entries on the project
	 * 
	 * @param path the path to find a build path entry for
	 * @param project the Java project
	 * @return the <code>IClasspathEntry</code> corresponding
	 * to the <code>path</code> or <code>null</code> if there
	 * is no such entry
	 * @throws JavaModelException
	 */
	public static IClasspathEntry getClasspathEntryFor(IPath path, IJavaProject project, int entryKind) throws JavaModelException {
		IClasspathEntry[] entries= project.getRawClasspath();
		for (int i= 0; i < entries.length; i++) {
			IClasspathEntry entry= entries[i];
			if (entry.getPath().equals(path) && equalEntryKind(entry, entryKind))
				return entry;
		}
		return null;
	}

	/**
	 * Check whether the current selection is the project's 
	 * default output folder or not
	 * 
	 * @param attrib the attribute to be checked
	 * @return <code>true</code> if is the default output folder,
	 * <code>false</code> otherwise.
	 */
	public static boolean isDefaultOutputFolder(CPListElementAttribute attrib) {
		return attrib.getValue() == null;
	}

	/**
	 * Determines whether the current selection (of type
	 * <code>ICompilationUnit</code> or <code>IPackageFragment</code>)
	 * is on the inclusion filter of it's parent source folder.
	 * 
	 * @param selection the current Java element
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return <code>true</code> if the current selection is included,
	 * <code>false</code> otherwise.
	 * @throws JavaModelException 
	 */
	public static boolean isIncluded(IJavaElement selection, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ContainsPath, 4); 
			IPackageFragmentRoot root= (IPackageFragmentRoot) selection.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
			IClasspathEntry entry= root.getRawClasspathEntry();
			if (entry == null)
				return false;
			return contains(selection.getPath().removeFirstSegments(root.getPath().segmentCount()), entry.getInclusionPatterns(), new SubProgressMonitor(monitor, 2));
		} finally {
			monitor.done();
		}
	}

	/**
	 * Find out whether the <code>IResource</code> excluded or not.
	 * 
	 * @param resource the resource to be checked
	 * @param project the Java project
	 * @return <code>true</code> if the resource is excluded, <code>
	 * false</code> otherwise
	 * @throws JavaModelException
	 */
	public static boolean isExcluded(IResource resource, IJavaProject project) throws JavaModelException {
		IPackageFragmentRoot root= getFragmentRoot(resource, project, null);
		if (root == null)
			return false;
		String fragmentName= getName(resource.getFullPath(), root.getPath());
		fragmentName= completeName(fragmentName);
		IClasspathEntry entry= root.getRawClasspathEntry();
		return entry != null && contains(new Path(fragmentName), entry.getExclusionPatterns(), null);
	}

	/**
	 * Find out whether one of the <code>IResource</code>'s parents
	 * is excluded.
	 * 
	 * @param resource check the resources parents whether they are
	 * excluded or not
	 * @param project the Java project
	 * @return <code>true</code> if there is an excluded parent, 
	 * <code>false</code> otherwise
	 * @throws JavaModelException
	 */
	public static boolean parentExcluded(IResource resource, IJavaProject project) throws JavaModelException {
		if (resource.getFullPath().equals(project.getPath()))
			return false;
		IPackageFragmentRoot root= getFragmentRoot(resource, project, null);
		if (root == null) {
			return true;
		}
		IPath path= resource.getFullPath().removeFirstSegments(root.getPath().segmentCount());
		IClasspathEntry entry= root.getRawClasspathEntry();
		if (entry == null)
			return true; // there is no build path entry, this is equal to the fact that the parent is excluded
		while (path.segmentCount() > 0) {
			if (contains(path, entry.getExclusionPatterns(), null))
				return true;
			path= path.removeLastSegments(1);
		}
		return false;
	}

	/**
	 * Check wheter the output location of the <code>IPackageFragmentRoot</code>
	 * is <code>null</code>. If this holds, then the root 
	 * does use the default output folder.
	 * 
	 * @param root the root to examine the output location for
	 * @return <code>true</code> if the root uses the default output folder, <code>false
	 * </code> otherwise.
	 * @throws JavaModelException
	 */
	public static boolean hasDefaultOutputFolder(IPackageFragmentRoot root) throws JavaModelException {
		return root.getRawClasspathEntry().getOutputLocation() == null;
	}

	/**
	 * Check whether at least one source folder of the given
	 * Java project has an output folder set.
	 * 
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return <code>true</code> if at least one outputfolder
	 * is set, <code>false</code> otherwise
	 * @throws JavaModelException 
	 */
	public static boolean hasOutputFolders(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			IPackageFragmentRoot[] roots= project.getPackageFragmentRoots();
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_CheckOutputFolders, roots.length); 
			for (int i= 0; i < roots.length; i++) {
				if (roots[i].getRawClasspathEntry().getOutputLocation() != null)
					return true;
				monitor.worked(1);
			}
		} finally {
			monitor.done();
		}
		return false;
	}
	
	public static String escapeSpecialChars(String value) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < value.length(); i++) {
			char c = value.charAt(i);

			switch (c) {
			case '&':
				buf.append("&amp;"); //$NON-NLS-1$
				break;
			case '<':
				buf.append("&lt;"); //$NON-NLS-1$
				break;
			case '>':
				buf.append("&gt;"); //$NON-NLS-1$
				break;
			case '\'':
				buf.append("&apos;"); //$NON-NLS-1$
				break;
			case '\"':
				buf.append("&quot;"); //$NON-NLS-1$
				break;
			case 160:
				buf.append(" "); //$NON-NLS-1$
				break;
			default:
				buf.append(c);
				break;
			}
		}
		return buf.toString();
	}
	

	/**
	 * Check whether the <code>IJavaProject</code>
	 * is a source folder 
	 * 
	 * @param project the project to test
	 * @return <code>true</code> if <code>project</code> is a source folder
	 * <code>false</code> otherwise.
	 */
	public static boolean isSourceFolder(IJavaProject project) throws JavaModelException {
		return ClasspathModifier.getClasspathEntryFor(project.getPath(), project, IClasspathEntry.CPE_SOURCE) != null;
	}
	
	/**
	 * Check whether the <code>IPackageFragment</code>
	 * corresponds to the project's default fragment.
	 * 
	 * @param fragment the package fragment to be checked
	 * @return <code>true</code> if is the default package fragment,
	 * <code>false</code> otherwise.
	 */
	public static boolean isDefaultFragment(IPackageFragment fragment) {
		return fragment.getElementName().length() == 0;
	}

	/**
	 * Determines whether the inclusion filter of the element's source folder is empty
	 * or not
	 * @return <code>true</code> if the inclusion filter is empty,
	 * <code>false</code> otherwise.
	 * @throws JavaModelException 
	 */
	public static boolean includeFiltersEmpty(IResource resource, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ExamineInputFilters, 4); 
			IPackageFragmentRoot root= getFragmentRoot(resource, project, new SubProgressMonitor(monitor, 4));
			if (root != null) {
				IClasspathEntry entry= root.getRawClasspathEntry();
				return entry.getInclusionPatterns().length == 0;
			}
			return true;
		} finally {
			monitor.done();
		}
	}

	/**
	 * Check whether the input paramenter of type <code>
	 * IPackageFragmentRoot</code> has either it's inclusion or
	 * exclusion filter or both set (that means they are
	 * not empty).
	 * 
	 * @param root the fragment root to be inspected
	 * @return <code>true</code> inclusion or exclusion filter set,
	 * <code>false</code> otherwise.
	 */
	public static boolean filtersSet(IPackageFragmentRoot root) throws JavaModelException {
		if (root == null)
			return false;
		IClasspathEntry entry= root.getRawClasspathEntry();
		IPath[] inclusions= entry.getInclusionPatterns();
		IPath[] exclusions= entry.getExclusionPatterns();
		if (inclusions != null && inclusions.length > 0)
			return true;
		if (exclusions != null && exclusions.length > 0)
			return true;
		return false;
	}

	/**
	 * Add a resource to the build path.
	 * 
	 * @param resource the resource to be added to the build path
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code> 
	 * @return returns the new element of type <code>IPackageFragmentRoot</code> that has been added to the build path
	 * @throws CoreException 
	 * @throws OperationCanceledException 
	 */
	public static CPListElement addToClasspath(IResource resource, List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 2); 
			exclude(resource.getFullPath(), existingEntries, newEntries, project, new SubProgressMonitor(monitor, 1));
			CPListElement entry= new CPListElement(project, IClasspathEntry.CPE_SOURCE, resource.getFullPath(), resource);
			return entry;
		} finally {
			monitor.done();
		}
	}

	/**
	 * Check whether the provided file is an archive (.jar or .zip).
	 * 
	 * @param file the file to be checked
	 * @param project the Java project
	 * @return <code>true</code> if the file is an archive, <code>false</code> 
	 * otherwise
	 * @throws JavaModelException
	 */
	public static boolean isArchive(IFile file, IJavaProject project) throws JavaModelException {
		if (!ArchiveFileFilter.isArchivePath(file.getFullPath()))
			return false;
		if (project != null && project.exists() && (project.findPackageFragmentRoot(file.getFullPath()) == null))
			return true;
		return false;
	}

	/**
	 * Add a Java element to the build path.
	 * 
	 * @param javaElement element to be added to the build path
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code> 
	 * @return returns the new element of type <code>IPackageFragmentRoot</code> that has been added to the build path
	 * @throws CoreException 
	 * @throws OperationCanceledException 
	 */
	public static CPListElement addToClasspath(IJavaElement javaElement, List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws OperationCanceledException, CoreException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_AddToBuildpath, 10); 
			CPListElement entry= new CPListElement(project, IClasspathEntry.CPE_SOURCE, javaElement.getPath(), javaElement.getResource());
			return entry;
		} finally {
			monitor.done();
		}
	}

	/**
	 * Remove the Java project from the build path
	 * 
	 * @param project the project to be removed
	 * @param existingEntries a list of existing <code>CPListElement</code>. This list 
	 * will be traversed and the entry for the project will be removed.
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return returns the Java project
	 */
	public static IJavaProject removeFromClasspath(IJavaProject project, List existingEntries, IProgressMonitor monitor) {
		CPListElement elem= getListElement(project.getPath(), existingEntries);
		if (elem != null) {
			existingEntries.remove(elem);
		}
		return project;
	}
	
	/**
	 * Remove <code>path</code> from inclusion/exlusion filters in all <code>existingEntries</code>
	 * 
	 * @param path the path to remove
	 * @param project the Java project
	 * @param existingEntries a list of <code>CPListElement</code> representing the build path
	 * entries of the project.
	 * @return returns a <code>List</code> of <code>CPListElement</code> of modified elements, not null.
	 */
	public static List removeFilters(IPath path, IJavaProject project, List existingEntries) {
		if (path == null)
			return Collections.EMPTY_LIST;
		
		IPath projPath= project.getPath();
		if (projPath.isPrefixOf(path)) {
			path= path.removeFirstSegments(projPath.segmentCount()).addTrailingSeparator();
		}
		
		List result= new ArrayList();
		for (Iterator iter= existingEntries.iterator(); iter.hasNext();) {
			CPListElement element= (CPListElement)iter.next();
			boolean hasChange= false;
			IPath[] exlusions= (IPath[])element.getAttribute(CPListElement.EXCLUSION);
			if (exlusions != null) {
				List exlusionList= new ArrayList(exlusions.length);
				for (int i= 0; i < exlusions.length; i++) {
					if (!exlusions[i].equals(path)) {
						exlusionList.add(exlusions[i]);
					} else {
						hasChange= true;
					}
				}
				element.setAttribute(CPListElement.EXCLUSION, exlusionList.toArray(new IPath[exlusionList.size()]));
			}
			
			IPath[] inclusion= (IPath[])element.getAttribute(CPListElement.INCLUSION);
			if (inclusion != null) {
				List inclusionList= new ArrayList(inclusion.length);
				for (int i= 0; i < inclusion.length; i++) {
					if (!inclusion[i].equals(path)) {
						inclusionList.add(inclusion[i]);
					} else {
						hasChange= true;
					}
				}
				element.setAttribute(CPListElement.INCLUSION, inclusionList.toArray(new IPath[inclusionList.size()]));
			}
			if (hasChange) {
				result.add(element);
			}
		}
		return result;
	}

	/**
	 * Exclude an element with a given name and absolute path
	 * from the build path.
	 * 
	 * @param name the name of the element to be excluded
	 * @param fullPath the absolute path of the element
	 * @param entry the build path entry to be modified
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return a <code>IResource</code> corresponding to the excluded element
	 * @throws JavaModelException 
	 */
	private static IResource exclude(String name, IPath fullPath, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		IResource result;
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, 6); 
			IPath[] excludedPath= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION);
			IPath[] newExcludedPath= new IPath[excludedPath.length + 1];
			name= completeName(name);
			IPath path= new Path(name);
			if (!contains(path, excludedPath, new SubProgressMonitor(monitor, 2))) {
				System.arraycopy(excludedPath, 0, newExcludedPath, 0, excludedPath.length);
				newExcludedPath[excludedPath.length]= path;
				entry.setAttribute(CPListElement.EXCLUSION, newExcludedPath);
				entry.setAttribute(CPListElement.INCLUSION, remove(path, (IPath[]) entry.getAttribute(CPListElement.INCLUSION), new SubProgressMonitor(monitor, 4)));
			}
			result= fullPath == null ? null : getResource(fullPath, project);
		} finally {
			monitor.done();
		}
		return result;
	}

	/**
	 * Exclude an object at a given path.
	 * This means that the exclusion filter for the
	 * corresponding <code>IPackageFragmentRoot</code> needs to be modified.
	 * 
	 * First, the fragment root needs to be found. To do so, the new entries 
	 * are and the existing entries are traversed for a match and the entry 
	 * with the path is removed from one of those lists.
	 * 
	 * Note: the <code>IJavaElement</code>'s fragment (if there is one)
	 * is not allowed to be excluded! However, inclusion (or simply no
	 * filter) on the parent fragment is allowed.
	 * 
	 * @param path absolute path of an object to be excluded
	 * @param existingEntries a list of existing build path entries
	 * @param newEntries a list of new build path entries
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 */
	public static void exclude(IPath path, List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_Excluding, 1); 
			CPListElement elem= null;
			CPListElement existingElem= null;
			int i= 0;
			do {
				i++;
				IPath rootPath= path.removeLastSegments(i);

				if (rootPath.segmentCount() == 0)
					return;

				elem= getListElement(rootPath, newEntries);
				existingElem= getListElement(rootPath, existingEntries);
			} while (existingElem == null && elem == null);
			if (elem == null) {
				elem= existingElem;
			}
			exclude(path.removeFirstSegments(path.segmentCount() - i).toString(), null, elem, project, new SubProgressMonitor(monitor, 1)); 
		} finally {
			monitor.done();
		}
	}

	/**
	 * Exclude a <code>IJavaElement</code>. This means that the exclusion filter for the
	 * corresponding <code>IPackageFragmentRoot</code>s need to be modified.
	 * 
	 * Note: the <code>IJavaElement</code>'s fragment (if there is one)
	 * is not allowed to be excluded! However, inclusion (or simply no
	 * filter) on the parent fragment is allowed.
	 * 
	 * @param javaElement the Java element to be excluded
	 * @param entry the <code>CPListElement</code> representing the 
	 * <code>IClasspathEntry</code> of the Java element's root.
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * 
	 * @return the resulting <code>IResource<code>
	 * @throws JavaModelException
	 */
	public static IResource exclude(IJavaElement javaElement, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			String name= getName(javaElement.getPath(), entry.getPath());
			return exclude(name, javaElement.getPath(), entry, project, new SubProgressMonitor(monitor, 1));
		} finally {
			monitor.done();
		}
	}

	/**
	 * Inverse operation to <code>exclude</code>.
	 * The resource removed from it's fragment roots exlusion filter.
	 * 
	 * Note: the <code>IJavaElement</code>'s fragment (if there is one)
	 * is not allowed to be excluded! However, inclusion (or simply no
	 * filter) on the parent fragment is allowed.
	 * 
	 * @param resource the resource to be unexcluded
	 * @param entry the <code>CPListElement</code> representing the 
	 * <code>IClasspathEntry</code> of the resource's root.
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @throws JavaModelException
	 * 
	 */
	public static void unExclude(IResource resource, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemoveExclusion, 10); 
			String name= getName(resource.getFullPath(), entry.getPath());
			IPath[] excludedPath= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION);
			IPath[] newExcludedPath= remove(new Path(completeName(name)), excludedPath, new SubProgressMonitor(monitor, 3));
			entry.setAttribute(CPListElement.EXCLUSION, newExcludedPath);
		} finally {
			monitor.done();
		}
	}

	/**
	 * Resets inclusion and exclusion filters for the given
	 * <code>IJavaElement</code>
	 * 
	 * @param element element to reset it's filters
	 * @param entry the <code>CPListElement</code> to reset its filters for
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @throws JavaModelException
	 */
	public static void resetFilters(IJavaElement element, CPListElement entry, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ResetFilters, 3); 

			List exclusionList= getFoldersOnCP(element.getPath(), project, new SubProgressMonitor(monitor, 2));
			IPath outputLocation= (IPath) entry.getAttribute(CPListElement.OUTPUT);
			if (outputLocation != null) {
				IPath[] exclusionPatterns= (IPath[]) entry.getAttribute(CPListElement.EXCLUSION);
				if (contains(new Path(completeName(outputLocation.lastSegment())), exclusionPatterns, null)) {
					exclusionList.add(new Path(completeName(outputLocation.lastSegment())));
				}
			}
			IPath[] exclusions= (IPath[]) exclusionList.toArray(new IPath[exclusionList.size()]);

			entry.setAttribute(CPListElement.INCLUSION, new IPath[0]);
			entry.setAttribute(CPListElement.EXCLUSION, exclusions);
		} finally {
			monitor.done();
		}
	}

	/**
	 * Reset the output folder for the given entry to the default output folder
	 * 
	 * @param entry the <code>CPListElement</code> to be edited
	 * @param project the Java project
	 * @return an attribute representing the modified output folder
	 * @throws JavaModelException 
	 */
	public static CPListElementAttribute resetOutputFolder(CPListElement entry, IJavaProject project) throws JavaModelException {
		entry.setAttribute(CPListElement.OUTPUT, null);
		CPListElementAttribute outputFolder= new CPListElementAttribute(entry, CPListElement.OUTPUT, entry.getAttribute(CPListElement.OUTPUT), true);
		return outputFolder;
	}

	/**
	 * Try to find the corresponding and modified <code>CPListElement</code> for the provided 
	 * <code>CPListElement</code> in the list of elements and return it.
	 * If no one can be found, the provided <code>CPListElement</code> is returned.
	 * 
	 * @param elements a list of <code>CPListElements</code>
	 * @param cpElement the <code>CPListElement</code> to find the corresponding entry in 
	 * the list
	 * @return the <code>CPListElement</code> found in the list (matching by using the path) or 
	 * the second <code>CPListElement</code> parameter itself if there is no match.
	 */
	public static CPListElement getClasspathEntry(List elements, CPListElement cpElement) {
		for (int i= 0; i < elements.size(); i++) {
			if (((CPListElement) elements.get(i)).getPath().equals(cpElement.getPath()))
				return (CPListElement) elements.get(i);
		}
		elements.add(cpElement);
		return cpElement;
	}

	/**
	 * For a given path, find the corresponding element in the list.
	 * 
	 * @param path the path to found an entry for
	 * @param elements a list of <code>CPListElement</code>s
	 * @return the mathed <code>CPListElement</code> or <code>null</code> if 
	 * no match could be found
	 */
	public static CPListElement getListElement(IPath path, List elements) {
		for (int i= 0; i < elements.size(); i++) {
			CPListElement element= (CPListElement) elements.get(i);
			if (element.getEntryKind() == IClasspathEntry.CPE_SOURCE && element.getPath().equals(path)) {
				return element;
			}
		}
		return null;
	}
	
	public static void commitClassPath(List newEntries, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		
		monitor.beginTask("", 2); //$NON-NLS-1$
		
		try {
			IClasspathEntry[] entries= convert(newEntries);
			IPath outputLocation= project.getOutputLocation();

			IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation);
			if (!status.isOK())
				throw new JavaModelException(status);

			project.setRawClasspath(entries, outputLocation, new SubProgressMonitor(monitor, 2));
		} finally {
			monitor.done();
		}
	}
	
    public static void commitClassPath(CPJavaProject cpProject, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		
		monitor.beginTask("", 2); //$NON-NLS-1$
		
		try {
			IClasspathEntry[] entries= convert(cpProject.getCPListElements());
			IPath outputLocation= cpProject.getDefaultOutputLocation();

			IJavaModelStatus status= JavaConventions.validateClasspath(cpProject.getJavaProject(), entries, outputLocation);
			if (!status.isOK())
				throw new JavaModelException(status);

			cpProject.getJavaProject().setRawClasspath(entries, outputLocation, new SubProgressMonitor(monitor, 2));
		} finally {
			monitor.done();
		}
    }

	/**
	 * For a given list of entries, find out what representation they 
	 * will have in the project and return a list with corresponding 
	 * elements.
	 * 
	 * @param entries a list of entries to find an appropriate representation 
	 * for. The list can contain elements of two types: 
	 * <li><code>IResource</code></li>
	 * <li><code>IJavaElement</code></li>
	 * @param project the Java project
	 * @return a list of elements corresponding to the passed entries.
	 */
	public static List getCorrespondingElements(List entries, IJavaProject project) {
		List result= new ArrayList();
		for (int i= 0; i < entries.size(); i++) {
			Object element= entries.get(i);
			IPath path;
			if (element instanceof IResource)
				path= ((IResource) element).getFullPath();
			else
				path= ((IJavaElement) element).getPath();
			IResource resource= getResource(path, project);
			if (resource != null) {
				IJavaElement elem= JavaCore.create(resource);
				if (elem != null && project.isOnClasspath(elem))
					result.add(elem);
				else
					result.add(resource);
			}

		}
		return result;
	}

	/**
	 * Returns for the given absolute path the corresponding
	 * resource, this is either element of type <code>IFile</code>
	 * or <code>IFolder</code>.
	 *  
	 * @param path an absolute path to a resource
	 * @param project the Java project
	 * @return the resource matching to the path. Can be
	 * either an <code>IFile</code> or an <code>IFolder</code>.
	 */
	private static IResource getResource(IPath path, IJavaProject project) {
		return project.getProject().getWorkspace().getRoot().findMember(path);
	}

	/**
	 * Find out whether the provided path equals to one
	 * in the array.
	 * 
	 * @param path path to find an equivalent for
	 * @param paths set of paths to compare with
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return <code>true</code> if there is an occurrence, <code>
	 * false</code> otherwise
	 */
	private static boolean contains(IPath path, IPath[] paths, IProgressMonitor monitor) {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		if (path == null)
			return false;
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_ComparePaths, paths.length); 
			if (path.getFileExtension() == null)
				path= new Path(completeName(path.toString())); 
			for (int i= 0; i < paths.length; i++) {
				if (paths[i].equals(path))
					return true;
				monitor.worked(1);
			}
		} finally {
			monitor.done();
		}
		return false;
	}

	/**
	 * Add a '/' at the end of the name if
	 * it does not end with '.java', or other Java-like extension.
	 * 
	 * @param name append '/' at the end if
	 * necessary
	 * @return modified string
	 */
	private static String completeName(String name) {
		if (!JavaCore.isJavaLikeFileName(name)) {
			name= name + "/"; //$NON-NLS-1$
			name= name.replace('.', '/');
			return name;
		}
		return name;
	}

	/**
	 * Removes <code>path</code> out of the set of given <code>
	 * paths</code>. If the path is not contained, then the 
	 * initially provided array of paths is returned.
	 * 
	 * Only the first occurrence will be removed.
	 * 
	 * @param path path to be removed
	 * @param paths array of path to apply the removal on
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return array which does not contain <code>path</code>
	 */
	private static IPath[] remove(IPath path, IPath[] paths, IProgressMonitor monitor) {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_RemovePath, paths.length + 5); 
			if (!contains(path, paths, new SubProgressMonitor(monitor, 5)))
				return paths;

			ArrayList newPaths= new ArrayList();
			for (int i= 0; i < paths.length; i++) {
				monitor.worked(1);
				if (!paths[i].equals(path))
					newPaths.add(paths[i]);
			}
			
			return (IPath[]) newPaths.toArray(new IPath[newPaths.size()]);
		} finally {
			monitor.done();
		}

	}

	/**
	 * Find all folders that are on the build path and
	 * <code>path</code> is a prefix of those folders
	 * path entry, that is, all folders which are a
	 * subfolder of <code>path</code>.
	 * 
	 * For example, if <code>path</code>=/MyProject/src 
	 * then all folders having a path like /MyProject/src/*,
	 * where * can be any valid string are returned if
	 * they are also on the project's build path.
	 * 
	 * @param path absolute path
	 * @param project the Java project
	 * @param monitor progress monitor, can be <code>null</code>
	 * @return an array of paths which belong to subfolders
	 * of <code>path</code> and which are on the build path
	 * @throws JavaModelException
	 */
	private static List getFoldersOnCP(IPath path, IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
		if (monitor == null)
			monitor= new NullProgressMonitor();
		List srcFolders= new ArrayList();
		IClasspathEntry[] cpEntries= project.getRawClasspath();
		for (int i= 0; i < cpEntries.length; i++) {
			IPath cpPath= cpEntries[i].getPath();
			if (path.isPrefixOf(cpPath) && path.segmentCount() + 1 == cpPath.segmentCount())
				srcFolders.add(new Path(completeName(cpPath.lastSegment())));
		}
		return srcFolders;
	}

	/**
	 * Returns a string corresponding to the <code>path</code>
	 * with the <code>rootPath<code>'s number of segments
	 * removed
	 * 
	 * @param path path to remove segments
	 * @param rootPath provides the number of segments to
	 * be removed
	 * @return a string corresponding to the mentioned
	 * action
	 */
	private static String getName(IPath path, IPath rootPath) {
		return path.removeFirstSegments(rootPath.segmentCount()).toString();
	}

	/**
	 * Sets and validates the new entries. Note that the elments of 
	 * the list containing the new entries will be added to the list of 
	 * existing entries (therefore, there is no return list for this method).
	 * 
	 * @param existingEntries a list of existing classpath entries
	 * @param newEntries a list of entries to be added to the existing ones
	 * @param project the Java project
	 * @param monitor a progress monitor, can be <code>null</code>
	 * @throws CoreException in case that validation on one of the new entries fails
	 */
	public static void setNewEntry(List existingEntries, List newEntries, IJavaProject project, IProgressMonitor monitor) throws CoreException {
		try {
			monitor.beginTask(NewWizardMessages.ClasspathModifier_Monitor_SetNewEntry, existingEntries.size()); 
			for (int i= 0; i < newEntries.size(); i++) {
				CPListElement entry= (CPListElement) newEntries.get(i);
				validateAndAddEntry(entry, existingEntries, project);
				monitor.worked(1);
			}
		} finally {
			monitor.done();
		}
	}

	/**
	 * Convert a list of <code>CPListElement</code>s to 
	 * an array of <code>IClasspathEntry</code>.
	 * 
	 * @param list the list to be converted
	 * @return an array containing build path entries 
	 * corresponding to the list
	 */
	private static IClasspathEntry[] convert(List list) {
		IClasspathEntry[] entries= new IClasspathEntry[list.size()];
		for (int i= 0; i < list.size(); i++) {
			CPListElement element= (CPListElement) list.get(i);
			entries[i]= element.getClasspathEntry();
		}
		return entries;
	}

	/**
	 * Validate the new entry in the context of the existing entries. Furthermore, 
	 * check if exclusion filters need to be applied and do so if necessary.
	 * 
	 * If validation was successfull, add the new entry to the list of existing entries.
	 * 
	 * @param entry the entry to be validated and added to the list of existing entries.
	 * @param existingEntries a list of existing entries representing the build path
	 * @param project the Java project
	 * @throws CoreException in case that validation fails
	 */
	private static void validateAndAddEntry(CPListElement entry, List existingEntries, IJavaProject project) throws CoreException {
		IPath path= entry.getPath();
		IPath projPath= project.getProject().getFullPath();
		IWorkspaceRoot workspaceRoot= ResourcesPlugin.getWorkspace().getRoot();
		IStatus validate= workspaceRoot.getWorkspace().validatePath(path.toString(), IResource.FOLDER);
		StatusInfo rootStatus= new StatusInfo();
		rootStatus.setOK();
		boolean isExternal= isExternalArchiveOrLibrary(entry, project);
		if (!isExternal && validate.matches(IStatus.ERROR) && !project.getPath().equals(path)) {
			rootStatus.setError(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_error_InvalidRootName, validate.getMessage())); 
			throw new CoreException(rootStatus);
		} else {
			if (!isExternal && !project.getPath().equals(path)) {
				IResource res= workspaceRoot.findMember(path);
				if (res != null) {
					if (res.getType() != IResource.FOLDER && res.getType() != IResource.FILE) {
						rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_NotAFolder); 
						throw new CoreException(rootStatus);
					}
				} else {
					URI projLocation= project.getProject().getLocationURI();
					if (projLocation != null) {
						IFileStore store= EFS.getStore(projLocation).getChild(path);
						if (store.fetchInfo().exists()) {
							rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_AlreadyExistingDifferentCase); 
							throw new CoreException(rootStatus);
						}
					}
				}
			}

			for (int i= 0; i < existingEntries.size(); i++) {
				CPListElement curr= (CPListElement) existingEntries.get(i);
				if (curr.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
					if (path.equals(curr.getPath()) && !project.getPath().equals(path)) {
						rootStatus.setError(NewWizardMessages.NewSourceFolderWizardPage_error_AlreadyExisting); 
						throw new CoreException(rootStatus);
					}
				}
			}

			if (!isExternal && !entry.getPath().equals(project.getPath()))
				exclude(entry.getPath(), existingEntries, new ArrayList(), project, null);

			IPath outputLocation= project.getOutputLocation();
			insertAtEndOfCategory(entry, existingEntries);

			IClasspathEntry[] entries= convert(existingEntries);

			IJavaModelStatus status= JavaConventions.validateClasspath(project, entries, outputLocation);
			if (!status.isOK()) {
				if (outputLocation.equals(projPath)) {
					IStatus status2= JavaConventions.validateClasspath(project, entries, outputLocation);
					if (status2.isOK()) {
						if (project.isOnClasspath(project)) {
							rootStatus.setInfo(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceSFandOL, outputLocation.makeRelative().toString())); 
						} else {
							rootStatus.setInfo(Messages.format(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceOL, outputLocation.makeRelative().toString())); 
						}
						return;
					}
				}
				rootStatus.setError(status.getMessage());
				throw new CoreException(rootStatus);
			}

			if (isSourceFolder(project) || project.getPath().equals(path)) {
				rootStatus.setWarning(NewWizardMessages.NewSourceFolderWizardPage_warning_ReplaceSF); 
				return;
			}

			rootStatus.setOK();
			return;
		}
	}

	private static void insertAtEndOfCategory(CPListElement entry, List existingEntries) {
		int length= existingEntries.size();
		CPListElement[] elements= (CPListElement[])existingEntries.toArray(new CPListElement[length]);
		int i= 0;
		while (i < length && elements[i].getClasspathEntry().getEntryKind() != entry.getClasspathEntry().getEntryKind()) {
			i++;
		}
		if (i < length) {
			i++;
			while (i < length && elements[i].getClasspathEntry().getEntryKind() == entry.getClasspathEntry().getEntryKind()) {
				i++;
			}
			existingEntries.add(i, entry);
			return;
		}
		
		switch (entry.getClasspathEntry().getEntryKind()) {
		case IClasspathEntry.CPE_SOURCE:
			existingEntries.add(0, entry);
			break;
		case IClasspathEntry.CPE_CONTAINER:
		case IClasspathEntry.CPE_LIBRARY:
		case IClasspathEntry.CPE_PROJECT:
		case IClasspathEntry.CPE_VARIABLE:
		default:
			existingEntries.add(entry);
			break;
		}
	}

	private static boolean isExternalArchiveOrLibrary(CPListElement entry, IJavaProject project) {
		if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY || entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
			if (entry.getResource() instanceof IFolder) {
				return false;
			}
			return true;
		}
		return false;
	}

	/**
	 * Test if the provided kind is of type
	 * <code>IClasspathEntry.CPE_SOURCE</code>
	 * 
	 * @param entry the classpath entry to be compared with the provided type
	 * @param kind the kind to be checked
	 * @return <code>true</code> if kind equals
	 * <code>IClasspathEntry.CPE_SOURCE</code>, 
	 * <code>false</code> otherwise
	 */
	private static boolean equalEntryKind(IClasspathEntry entry, int kind) {
		return entry.getEntryKind() == kind;
	}

	public static OutputFolderValidator getValidator(final List newElements, final IJavaProject project) throws JavaModelException {
		return new OutputFolderValidator(newElements, project) {

			public boolean validate(IPath outputLocation) {
				for (int i= 0; i < newElements.size(); i++) {
					if (isInvalid(newElements.get(i), outputLocation))
						return false;
				}

				for (int i= 0; i < fEntries.length; i++) {
					if (isInvalid(fEntries[i], outputLocation))
						return false;
				}
				return true;
			}

			/**
			 * Check if the output location for the given object is valid
			 * 
			 * @param object the object to retrieve its path from and compare it 
			 * to the output location
			 * @param outputLocation the output location
			 * @return <code>true</code> if the output location is invalid, that is, 
			 * if it is a subfolder of the provided object.
			 */
			private boolean isInvalid(Object object, IPath outputLocation) {
				IPath path= null;
				if (object instanceof IFolder)
					path= getFolderPath(object);
				else
					if (object instanceof IJavaElement)
						path= getJavaElementPath(object);
					else
						if (object instanceof IClasspathEntry)
							path= getCPEntryPath(object);
				return isSubFolderOf(path, outputLocation);
			}

			/**
			 * Get an <code>IFolder</code>'s path
			 * 
			 * @param element an element which is of type <code>IFolder</code>
			 * @return the path of the folder
			 */
			private IPath getFolderPath(Object element) {
				return ((IFolder) element).getFullPath();
			}

			/**
			 * Get an <code>IJavaElement</code>'s path
			 * 
			 * @param element an element which is of type <code>IJavaElement</code>
			 * @return the path of the Java element
			 */
			private IPath getJavaElementPath(Object element) {
				return ((IJavaElement) element).getPath();
			}

			/**
			 * Get an <code>IClasspathEntry</code>'s path
			 * 
			 * @param entry an element which is of type <code>IClasspathEntry</code>
			 * @return the path of the classpath entry
			 */
			private IPath getCPEntryPath(Object entry) {
				return ((IClasspathEntry) entry).getPath();
			}

			/**
			 * 
			 * @param path1 the first path
			 * @param path2 the second path
			 * @return <code>true</code> if path1 is a subfolder of 
			 * path2, <code>false</code> otherwise
			 */
			private boolean isSubFolderOf(IPath path1, IPath path2) {
				if (path1 == null || path2 == null) {
					if (path1 == null && path2 == null)
						return true;
					return false;
				}
				return path2.matchingFirstSegments(path1) == path2.segmentCount();
			}

		};
	}

}
