package eu.hohenegger.modulebuilder;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.ICommand;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

public class ProjectFactory {
	public static IJavaProject makeJavaProject(IProject project, IProgressMonitor monitor, String javaVersion) throws CoreException {
		addNature(project, monitor, JavaCore.NATURE_ID, "org.eclipse.pde.PluginNature");
		IJavaProject javaProject = JavaCore.create(project);
		addBuilders(project, monitor);
		addBinPath(project, javaProject, monitor);
		defineClassPathEntries(javaProject, javaVersion);
		return javaProject;
	}

	private static void addBuilders(IProject project, IProgressMonitor monitor) throws CoreException {
		IProjectDescription projectDescription = project.getDescription();
		final ICommand java = projectDescription.newCommand();
		java.setBuilderName(JavaCore.BUILDER_ID);

		final ICommand manifest = projectDescription.newCommand();
		manifest.setBuilderName("org.eclipse.pde.ManifestBuilder");

		final ICommand schema = projectDescription.newCommand();
		schema.setBuilderName("org.eclipse.pde.SchemaBuilder");

		projectDescription.setBuildSpec(new ICommand[] { java, manifest, schema });

		project.open(monitor);
		project.setDescription(projectDescription, monitor);
	}

	private static void addNature(IProject project, IProgressMonitor monitor, String... natures) throws CoreException {
		IProjectDescription description = project.getDescription();
		description.setNatureIds(natures);
		project.setDescription(description, monitor);
	}

	public static IResource createJavaPackage(IJavaProject javaProject, IFolder sourceFolder, IProgressMonitor monitor)
			throws JavaModelException {
		IPackageFragment packageFragment = javaProject.getPackageFragmentRoot(sourceFolder)
				.createPackageFragment(javaProject.getElementName(), false, monitor);
		return packageFragment.getCorrespondingResource();
	}

	public static void addToClassPathEntries(IJavaProject javaProject, IFolder sourceFolder, IProgressMonitor monitor)
			throws JavaModelException {
		IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(sourceFolder);
		IClasspathEntry[] oldEntries = javaProject.getRawClasspath();
		IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
		System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
		newEntries[oldEntries.length] = JavaCore.newSourceEntry(root.getPath());
		javaProject.setRawClasspath(newEntries, monitor);
	}

	public static IFolder addSourcePath(IProject project, IProgressMonitor monitor) throws CoreException {
		return createFolder("src", project, monitor);
	}

	public static IFolder createFolder(String folderName, IProject project, IProgressMonitor monitor) throws CoreException {
		IFolder sourceFolder = project.getFolder(folderName);
		sourceFolder.create(false, true, monitor);
		return sourceFolder;
	}

	private static void defineClassPathEntries(IJavaProject javaProject, String javaVersion) throws JavaModelException {
		List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();

		// TODO: remove: alternate way to add java libs
		// IVMInstall vmInstall = JavaRuntime.getDefaultVMInstall();
		// LibraryLocation[] locations =
		// JavaRuntime.getLibraryLocations(vmInstall);
		// for (LibraryLocation element : locations) {
		// entries.add(JavaCore.newLibraryEntry(element.getSystemLibraryPath(),
		// null, null));
		// }
		entries.add(JavaCore.newContainerEntry(new Path(
				"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/"
						+ javaVersion)));
		entries.add(JavaCore.newContainerEntry(new Path("org.eclipse.pde.core.requiredPlugins")));

		// add libs to project class path
		javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);

	}

	private static void addBinPath(IProject project, IJavaProject javaProject, IProgressMonitor monitor) throws CoreException {
		IFolder binFolder = project.getFolder("bin");
		binFolder.create(false, true, monitor);
		javaProject.setOutputLocation(binFolder.getFullPath(), monitor);
	}

	public static IProject createProject(String projectName, IProgressMonitor monitor) throws CoreException {
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IProject project = root.getProject(projectName);
		if (!project.exists()) {
			project.create(monitor);
			project.open(monitor);
		}
		return project;
	}
}

@@ -3486,16 +3486,49 @@
 rName);%0A
+%09%09if (!sourceFolder.exists()) %7B%0A%09
 %09%09source
@@ -3556,32 +3556,36 @@
 true, monitor);%0A
+%09%09%7D%0A
 %09%09return sourceF
@@ -4707,16 +4707,46 @@
 %22bin%22);%0A
+%09%09if (!binFolder.exists()) %7B%0A%09
 %09%09binFol
@@ -4779,16 +4779,17 @@
 nitor);%0A
+%09
 %09%09javaPr
@@ -4839,32 +4839,36 @@
 th(), monitor);%0A
+%09%09%7D%0A
 %09%7D%0A%0A%09public stat

Enable overwriting existing core project