<commit_before>/*
 * Copyright 2016 DiffPlug
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.diffplug.gradle.oomph;

import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.annotation.Nonnull;
import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.XmlProvider;
import org.gradle.api.specs.Spec;
import org.gradle.api.specs.Specs;
import org.gradle.internal.Actions;
import org.gradle.plugins.ide.eclipse.GenerateEclipseProject;

import com.diffplug.common.base.Errors;
import com.diffplug.common.base.Preconditions;
import com.diffplug.common.base.Unhandled;
import com.diffplug.common.primitives.Booleans;
import com.diffplug.common.swt.os.OS;
import com.diffplug.common.swt.os.SwtPlatform;
import com.diffplug.gradle.ConfigMisc;
import com.diffplug.gradle.FileMisc;
import com.diffplug.gradle.GoomphCacheLocations;
import com.diffplug.gradle.JavaExecable;
import com.diffplug.gradle.Lazyable;
import com.diffplug.gradle.StateBuilder;
import com.diffplug.gradle.eclipserunner.EclipseIni;
import com.diffplug.gradle.oomph.thirdparty.ConventionThirdParty;
import com.diffplug.gradle.p2.P2Declarative;
import com.diffplug.gradle.p2.P2Model;
import com.diffplug.gradle.p2.P2Model.DirectorApp;
import com.diffplug.gradle.pde.EclipseRelease;
import com.diffplug.gradle.pde.PdeInstallation;

/** DSL for {@link OomphIdePlugin}. */
public class OomphIdeExtension implements P2Declarative {
	public static final String NAME = "oomphIde";

	final Project project;
	final WorkspaceRegistry workspaceRegistry;
	final SortedSet<File> projectFiles = new TreeSet<>();
	final Map<String, Object> workspaceFiles = new HashMap<>();
	final Map<String, Action<Map<String, String>>> workspaceProps = new HashMap<>();
	final Map<String, Action<XmlProvider>> workspaceXmls = new HashMap<>();
	final P2Model p2 = new P2Model();
	final Lazyable<List<SetupAction>> setupActions = Lazyable.ofList();

	@Nonnull
	String name;
	@Nonnull
	String description;
	@Nonnull
	String perspective;
	@Nonnull
	Object ideDir = "build/oomph-ide" + FileMisc.macApp();
	@Nonnull
	Action<DirectorApp> directorModifier = Actions.doNothing();
	@Nonnull
	Action<DirectorApp> runP2Using;

	Action<EclipseIni> eclipseIni;

	Object icon, splash;

	public OomphIdeExtension(Project project) throws IOException {
		this.project = Objects.requireNonNull(project);
		this.workspaceRegistry = WorkspaceRegistry.instance();
		this.name = project.getRootProject().getName();
		this.description = this.name;
		this.perspective = Perspectives.RESOURCES;
		this.runP2Using = app -> Errors.rethrow().run(() -> app.runUsingBootstrapper(project));
	}

	/** Returns the underlying project. */
	public Project getProject() {
		return project;
	}

	/** Returns the P2 model so that users can add the features they'd like. */
	@Override
	public P2Model getP2() {
		return p2;
	}

	/** Allows for fine-grained manipulation of the mirroring operation. */
	public void p2director(Action<DirectorApp> directorModifier) {
		this.directorModifier = Objects.requireNonNull(directorModifier);
	}

	/** Sets the icon image - any size and format is okay, but something square is recommended. */
	public void icon(Object icon) {
		this.icon = Objects.requireNonNull(icon);
	}

	/** Sets the splash screen image - any size and format is okay. */
	public void splash(Object splash) {
		this.splash = Objects.requireNonNull(splash);
	}

	/** Sets the name of the generated IDE.  Defaults to the name of the root project. */
	public void name(String name) {
		this.name = Objects.requireNonNull(name);
	}

	/** Sets the description of the generated IDE.  Defaults to name. */
	public void description(String description) {
		this.description = Objects.requireNonNull(description);
	}

	/** Sets the starting perspective (window layout), see {@link Perspectives} for common perspectives. */
	public void perspective(String perspective) {
		this.perspective = Objects.requireNonNull(perspective);
	}

	/** Sets properties in the `eclipse.ini`. */
	public void eclipseIni(Action<EclipseIni> eclipseIni) {
		Preconditions.checkArgument(this.eclipseIni == null, "Can only set eclipseIni once");
		this.eclipseIni = eclipseIni;
	}

	/** Sets the folder where the ide will be built. */
	public void ideDir(Object ideDir) {
		this.ideDir = Objects.requireNonNull(ideDir);
	}

	/** Adds all eclipse projects from all gradle projects. */
	public void addAllProjects() {
		addAllProjects(Specs.satisfyAll());
	}

	/** Adds all eclipse projects from all gradle projects whose paths meet the given spec. */
	public void addAllProjects(Spec<String> include) {
		project.getRootProject().getAllprojects().forEach(p -> {
			// this project is automatically included by logic
			// in OomphIdePlugin
			if (p == project) {
				return;
			}
			// this project depends on all the others
			if (include.isSatisfiedBy(p.getPath())) {
				addDependency(project.evaluationDependsOn(p.getPath()));
			}
		});
	}

	/** Adds the eclipse project from the given project path. */
	public void addProject(String projectPath) {
		addDependency(project.evaluationDependsOn(projectPath));
	}

	private static final String DOT_PROJECT = ".project";

	/** Adds the eclipse tasks from the given project as a dependency of our IDE setup task. */
	void addDependency(Project eclipseProject) {
		Task ideSetup = project.getTasks().getByName(OomphIdePlugin.IDE_SETUP_WORKSPACE);
		eclipseProject.getTasks().all(task -> {
			if ("eclipse".equals(task.getName())) {
				ideSetup.dependsOn(task);
			}
			if (task instanceof GenerateEclipseProject) {
				File projectFile = ((GenerateEclipseProject) task).getOutputFile();
				Preconditions.checkArgument(projectFile.getName().equals(DOT_PROJECT), "Project file must be '" + DOT_PROJECT + "', was %s", projectFile);
				projectFiles.add(projectFile);
			}<commit_msg>When buildship evaluates OomphIde, GenerateEclipseProject.getOutputFile() returns a null value.  Not sure why, but easy to work around.<commit_after>/*
 * Copyright 2016 DiffPlug
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.diffplug.gradle.oomph;

import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.annotation.Nonnull;
import javax.imageio.ImageIO;

import org.apache.commons.io.FileUtils;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.XmlProvider;
import org.gradle.api.specs.Spec;
import org.gradle.api.specs.Specs;
import org.gradle.internal.Actions;
import org.gradle.plugins.ide.eclipse.GenerateEclipseProject;

import com.diffplug.common.base.Errors;
import com.diffplug.common.base.Preconditions;
import com.diffplug.common.base.Unhandled;
import com.diffplug.common.primitives.Booleans;
import com.diffplug.common.swt.os.OS;
import com.diffplug.common.swt.os.SwtPlatform;
import com.diffplug.gradle.ConfigMisc;
import com.diffplug.gradle.FileMisc;
import com.diffplug.gradle.GoomphCacheLocations;
import com.diffplug.gradle.JavaExecable;
import com.diffplug.gradle.Lazyable;
import com.diffplug.gradle.StateBuilder;
import com.diffplug.gradle.eclipserunner.EclipseIni;
import com.diffplug.gradle.oomph.thirdparty.ConventionThirdParty;
import com.diffplug.gradle.p2.P2Declarative;
import com.diffplug.gradle.p2.P2Model;
import com.diffplug.gradle.p2.P2Model.DirectorApp;
import com.diffplug.gradle.pde.EclipseRelease;
import com.diffplug.gradle.pde.PdeInstallation;

/** DSL for {@link OomphIdePlugin}. */
public class OomphIdeExtension implements P2Declarative {
	public static final String NAME = "oomphIde";

	final Project project;
	final WorkspaceRegistry workspaceRegistry;
	final SortedSet<File> projectFiles = new TreeSet<>();
	final Map<String, Object> workspaceFiles = new HashMap<>();
	final Map<String, Action<Map<String, String>>> workspaceProps = new HashMap<>();
	final Map<String, Action<XmlProvider>> workspaceXmls = new HashMap<>();
	final P2Model p2 = new P2Model();
	final Lazyable<List<SetupAction>> setupActions = Lazyable.ofList();

	@Nonnull
	String name;
	@Nonnull
	String description;
	@Nonnull
	String perspective;
	@Nonnull
	Object ideDir = "build/oomph-ide" + FileMisc.macApp();
	@Nonnull
	Action<DirectorApp> directorModifier = Actions.doNothing();
	@Nonnull
	Action<DirectorApp> runP2Using;

	Action<EclipseIni> eclipseIni;

	Object icon, splash;

	public OomphIdeExtension(Project project) throws IOException {
		this.project = Objects.requireNonNull(project);
		this.workspaceRegistry = WorkspaceRegistry.instance();
		this.name = project.getRootProject().getName();
		this.description = this.name;
		this.perspective = Perspectives.RESOURCES;
		this.runP2Using = app -> Errors.rethrow().run(() -> app.runUsingBootstrapper(project));
	}

	/** Returns the underlying project. */
	public Project getProject() {
		return project;
	}

	/** Returns the P2 model so that users can add the features they'd like. */
	@Override
	public P2Model getP2() {
		return p2;
	}

	/** Allows for fine-grained manipulation of the mirroring operation. */
	public void p2director(Action<DirectorApp> directorModifier) {
		this.directorModifier = Objects.requireNonNull(directorModifier);
	}

	/** Sets the icon image - any size and format is okay, but something square is recommended. */
	public void icon(Object icon) {
		this.icon = Objects.requireNonNull(icon);
	}

	/** Sets the splash screen image - any size and format is okay. */
	public void splash(Object splash) {
		this.splash = Objects.requireNonNull(splash);
	}

	/** Sets the name of the generated IDE.  Defaults to the name of the root project. */
	public void name(String name) {
		this.name = Objects.requireNonNull(name);
	}

	/** Sets the description of the generated IDE.  Defaults to name. */
	public void description(String description) {
		this.description = Objects.requireNonNull(description);
	}

	/** Sets the starting perspective (window layout), see {@link Perspectives} for common perspectives. */
	public void perspective(String perspective) {
		this.perspective = Objects.requireNonNull(perspective);
	}

	/** Sets properties in the `eclipse.ini`. */
	public void eclipseIni(Action<EclipseIni> eclipseIni) {
		Preconditions.checkArgument(this.eclipseIni == null, "Can only set eclipseIni once");
		this.eclipseIni = eclipseIni;
	}

	/** Sets the folder where the ide will be built. */
	public void ideDir(Object ideDir) {
		this.ideDir = Objects.requireNonNull(ideDir);
	}

	/** Adds all eclipse projects from all gradle projects. */
	public void addAllProjects() {
		addAllProjects(Specs.satisfyAll());
	}

	/** Adds all eclipse projects from all gradle projects whose paths meet the given spec. */
	public void addAllProjects(Spec<String> include) {
		project.getRootProject().getAllprojects().forEach(p -> {
			// this project is automatically included by logic
			// in OomphIdePlugin
			if (p == project) {
				return;
			}
			// this project depends on all the others
			if (include.isSatisfiedBy(p.getPath())) {
				addDependency(project.evaluationDependsOn(p.getPath()));
			}
		});
	}

	/** Adds the eclipse project from the given project path. */
	public void addProject(String projectPath) {
		addDependency(project.evaluationDependsOn(projectPath));
	}

	private static final String DOT_PROJECT = ".project";

	/** Adds the eclipse tasks from the given project as a dependency of our IDE setup task. */
	void addDependency(Project eclipseProject) {
		Task ideSetup = project.getTasks().getByName(OomphIdePlugin.IDE_SETUP_WORKSPACE);
		eclipseProject.getTasks().all(task -> {
			if ("eclipse".equals(task.getName())) {
				ideSetup.dependsOn(task);
			}
			if (task instanceof GenerateEclipseProject) {
				File projectFile = ((GenerateEclipseProject) task).getOutputFile();
				if (projectFile == null) {
					project.getLogger().warn("eclipse task " + task + " has no project file");
				} else {
					Preconditions.checkArgument(projectFile.getName().equals(DOT_PROJECT), "Project file must be '" + DOT_PROJECT + "', was %s", projectFile);
					projectFiles.add(projectFile);
				}
			}
{'fraction_non_alphanumeric': 0.10881050978152221, 'fraction_numerical': 0.0035698986148793373, 'mean_word_length': 4.759457236842105, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2891198', 'n_tokens_mistral': 4481, 'n_tokens_neox': 4162, 'n_words': 1149}