<!--
  ~ Copyright 2010 the original author or authors.
  ~
  ~ 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.
  -->

<chapter id="eclipse_plugin">
    <title>The Eclipse Plugins</title>
    
    <para>The Eclipse plugins generate files that are used by the <ulink url="http://eclipse.org">Eclipse IDE</ulink>, thus
        making it possible to import the project into Eclipse (<guimenuitem>File</guimenuitem> - <guimenuitem>Import...</guimenuitem> - <guimenuitem>Existing Projects into Workspace</guimenuitem>).
        Both external dependencies (including associated source and Javadoc files) and project dependencies are considered.</para>

    <para>Since version 1.0-milestone-4 of Gradle, the WTP-generating code was refactored into a separate plugin called <literal>eclipse-wtp</literal>.
        So if you are interested in WTP integration then only apply the <literal>eclipse-wtp</literal> plugin. Otherwise applying the <literal>eclipse</literal> plugin is enough.
        This change was requested by Eclipse users who take advantage of the <literal>war</literal> or <literal>ear</literal> plugins,
        but who don't use Eclipse WTP. Internally, the <literal>eclipse-wtp</literal> plugin also applies the <literal>eclipse</literal> plugin so you don't need to apply both of those plugins.
    </para>

    <para>What exactly the <literal>eclipse</literal> plugin generates depends on which other plugins are used:</para>
    <table>
        <title>Eclipse plugin behavior</title>
        <thead>
            <tr><td>Plugin</td><td>Description</td></tr>
        </thead>
        <tr>
            <td>None</td><td>Generates minimal <filename>.project</filename> file.</td>
        </tr>
        <tr>
            <td><link linkend="java_plugin">Java</link></td><td>Adds Java configuration to <filename>.project</filename>.
            Generates <filename>.classpath</filename> and JDT settings file.</td>
        </tr>
        <tr>
            <td><link linkend="groovy_plugin">Groovy</link></td><td>Adds Groovy configuration to <filename>.project</filename> file.</td>
        </tr>
        <tr>
            <td><link linkend="scala_plugin">Scala</link></td><td>Adds Scala support to <filename>.project</filename> and <filename>.classpath</filename> files.</td>
        </tr>
        <tr>
            <td><link linkend="war_plugin">War</link></td><td>Adds web application support to <filename>.project</filename> file.</td>
        </tr>
        <tr>
            <td><link linkend="ear_plugin">Ear</link></td><td>Adds ear application support to <filename>.project</filename> file.</td>
        </tr>
    </table>

    <para>However, the <literal>eclipse-wtp</literal> plugin <emphasis>always</emphasis> generates all WTP settings files and enhances the
        <filename>.project</filename> file. If a <link linkend="java_plugin">Java</link> or <link linkend="war_plugin">War</link> is applied,
        <filename>.classpath</filename> will be extended to get a proper packaging structure for this utility library or web
        application project.
    </para>

    <para>Both Eclipse plugins are open to customization and provide a standardized set of hooks
        for adding and removing content from the generated files.
    </para>

    <section>
        <title>Usage</title>
        <para>To use either the Eclipse or the Eclipse WTP plugin, include one of the lines in your build script:</para>

        <sample id="useEclipsePlugin" dir="eclipse" title="Using the Eclipse plugin">
            <sourcefile file="build.gradle" snippet="use-eclipse-plugin"/>
        </sample>
        <sample id="useEclipseWtpPlugin" dir="eclipse" title="Using the Eclipse WTP plugin">
            <sourcefile file="build.gradle" snippet="use-eclipse-wtp-plugin"/>
        </sample>

        <para><emphasis>Note: </emphasis> Internally, the <literal>eclipse-wtp</literal> plugin also applies the
            <literal>eclipse</literal> plugin so you don't need to apply both.</para>

        <para>Both Eclipse plugins add a number of tasks to your projects. The main tasks that you will use
            are the <literal>eclipse</literal> and <literal>cleanEclipse</literal> tasks.
        </para>
    </section>
    <section>
        <title>Tasks</title>

        <para>The Eclipse plugins add the tasks shown below to a project.</para>

        <table id='eclipsetasks'>
            <title>Eclipse plugin - tasks</title>
            <thead>
                <tr>
                    <td>Task name</td>
                    <td>Depends on</td>
                    <td>Type</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>eclipse</literal>
                </td>
                <td>all Eclipse configuration file generation tasks</td>
                <td><apilink class="org.gradle.api.Task"/></td>
                <td>Generates all Eclipse configuration files</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipse</literal>
                </td>
                <td>all Eclipse configuration file clean tasks</td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes all Eclipse configuration files</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseProject</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the <filename>.project</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseClasspath</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the <filename>.classpath</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseJdt</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the <filename>.settings/org.eclipse.jdt.core.prefs</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseProject</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.GenerateEclipseProject"/></td>
                <td>Generates the <filename>.project</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseClasspath</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.GenerateEclipseClasspath"/></td>
                <td>Generates the <filename>.classpath</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseJdt</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.GenerateEclipseJdt"/></td>
                <td>Generates the <filename>.settings/org.eclipse.jdt.core.prefs</filename> file.</td>
            </tr>
        </table>
        <table id='eclipsewtptasks'>
            <title>Eclipse WTP plugin - additional tasks</title>
            <thead>
                <tr>
                    <td>Task name</td>
                    <td>Depends on</td>
                    <td>Type</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <literal>cleanEclipseWtpComponent</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.api.tasks.Delete"/></td>
                <td>Removes the <filename>.settings/org.eclipse.wst.common.component</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>cleanEclipseWtpFacet</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td>
                    <apilink class="org.gradle.api.tasks.Delete"/>
                </td>
                <td>Removes the <filename>.settings/org.eclipse.wst.common.project.facet.core.xml</filename> file.
                </td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseWtpComponent</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td><apilink class="org.gradle.plugins.ide.eclipse.GenerateEclipseWtpComponent"/></td>
                <td>Generates the <filename>.settings/org.eclipse.wst.common.component</filename> file.</td>
            </tr>
            <tr>
                <td>
                    <literal>eclipseWtpFacet</literal>
                </td>
                <td>
                    <literal>-</literal>
                </td>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.GenerateEclipseWtpFacet"/>
                </td>
                <td>Generates the <filename>.settings/org.eclipse.wst.common.project.facet.core.xml</filename> file.</td>
            </tr>
        </table>
    </section>
    <section>
        <title>Configuration</title>

        <table id='eclipse-configuration'>
            <title>Configuration of the Eclipse plugins</title>
            <thead>
                <tr>
                    <td>Model</td>
                    <td>Reference name</td>
                    <td>Description</td>
                </tr>
            </thead>
            <tr>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.model.EclipseModel"/>
                </td>
                <td><literal>eclipse</literal></td>
                <td>Top level element that enables configuration of the Eclipse plugin in a DSL-friendly fashion.</td>
            </tr>
            <tr>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.model.EclipseProject"/>
                </td>
                <td><literal>eclipse.project</literal></td>
                <td>Allows configuring project information</td>
            </tr>
            <tr>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.model.EclipseClasspath"/>
                </td>
                <td><literal>eclipse.classpath</literal></td>
                <td>Allows configuring classpath information.</td>
            </tr>
            <tr>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.model.EclipseJdt"/>
                </td>
                <td><literal>eclipse.jdt</literal></td>
                <td>Allows configuring jdt information (source/target Java compatibility).</td>
            </tr>
            <tr>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.model.EclipseWtpComponent"/>
                </td>
                <td><literal>eclipse.wtp.component</literal></td>
                <td>Allows configuring wtp component information only if <literal>eclipse-wtp</literal> plugin was applied.</td>
            </tr>
            <tr>
                <td>
                    <apilink class="org.gradle.plugins.ide.eclipse.model.EclipseWtpFacet"/>
                </td>
                <td><literal>eclipse.wtp.facet</literal></td>
                <td>Allows configuring wtp facet information only if <literal>eclipse-wtp</literal> plugin was applied.</td>
            </tr>
        </table>
    </section>
    <section>
        <title>Customizing the generated files</title>
        <para>
            The Eclipse plugins allow you to customize the generated metadata files. The plugins provide a DSL for configuring model objects
            that model the Eclipse view of the project. These model objects are then merged with the existing Eclipse XML metadata to ultimately
            generate new metadata. The model objects provide lower level hooks for working with domain objects representing the file content 
            before and after merging with the model configuration. They also provide a very low level hook for working directly with the raw 
            XML for adjustment before it is persisted, for fine tuning and configuration that the Eclipse and Eclipse WTP plugins do not model.
        </para>
        <section>
            <title>Merging</title>
            <para>Sections of existing Eclipse files that are also the target of generated content will be amended or overwritten,
                 depending on the particular section. The remaining sections will be left as-is.</para>
            <section id="sec:complete-rewrite">
                <title>Disabling merging with a complete rewrite</title>
                <para>To completely rewrite existing Eclipse files, execute a clean task together with its corresponding generation task,
                    like “<userinput>gradle cleanEclipse eclipse</userinput>” (in that order). If you want to make this
                    the default behavior, add “<code>tasks.eclipse.dependsOn(cleanEclipse)</code>” to your build script. This makes it
                    unnecessary to execute the clean task explicitly.
                </para>
                <para>This strategy can also be used for individual files that the plugins would generate. For instance,
                    this can be done for the “<literal>.classpath</literal>” file with “<userinput>gradle cleanEclipseClasspath eclipseClasspath</userinput>”.
                </para>
            </section>
        </section>
        <section>
            <title>Hooking into the generation lifecycle</title>
            <para>The Eclipse plugins provide objects modeling the sections of the Eclipse files
                that are generated by Gradle. The generation lifecycle is as follows:
                <orderedlist>
                    <listitem>The file is read; or a default version provided by Gradle is used if it does not exist</listitem>
                    <listitem>The <code>beforeMerged</code> hook is executed with a domain object representing the existing file</listitem>
                    <listitem>The existing content is merged with the configuration inferred from the Gradle build or defined explicitly in the eclipse DSL</listitem>
                    <listitem>The <code>whenMerged</code> hook is executed with a domain object representing contents of the file to be persisted</listitem>
                    <listitem>The <code>withXml</code> hook is executed with a raw representation of the XML that will be persisted</listitem>
                    <listitem>The final XML is persisted</listitem>
                </orderedlist>
                The following table lists the domain object used for each of the Eclipse model types:
            </para>
            <table id='eclipse-plugin-hooks'>
                <title>Advanced configuration hooks</title>
                <thead>
                    <tr>
                        <td>Model</td>
                        <td><literal>beforeMerged { arg -> }</literal> argument type</td>
                        <td><literal>whenMerged { arg -> }</literal> argument type</td>
                        <td><literal>withXml { arg -> }</literal> argument type</td>
                        <td><literal>withProperties { arg -> }</literal> argument type</td>
                    </tr>
                </thead>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.EclipseProject"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Project"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Project"/></td>
                    <td><apilink class="org.gradle.api.XmlProvider"/></td>
                    <td>-</td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.EclipseClasspath"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Classpath"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Classpath"/></td>
                    <td><apilink class="org.gradle.api.XmlProvider"/></td>
                    <td>-</td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.EclipseJdt"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Jdt"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.Jdt"/></td>
                    <td>-</td>
                    <td><ulink url="http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html"><code>java.util.Properties</code></ulink></td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.EclipseWtpComponent"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpComponent"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpComponent"/></td>
                    <td><apilink class="org.gradle.api.XmlProvider"/></td>
                    <td>-</td>
                </tr>
                <tr>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.EclipseWtpFacet"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpFacet"/></td>
                    <td><apilink class="org.gradle.plugins.ide.eclipse.model.WtpFacet"/></td>
                    <td><apilink class="org.gradle.api.XmlProvider"/></td>
                    <td>-</td>
                </tr>
            </table>
            <section id="sec:partial-overwrite">
                <title>Partial overwrite of existing content</title>
                <para>A <link linkend="sec:complete-overwrite">complete overwrite</link> causes all existing content to be discarded,
                    thereby losing any changes made directly in the IDE. Alternatively, the <code>beforeMerged</code> hook makes it possible
                    to overwrite just certain parts of the existing content. The following example removes all existing dependencies
                    from the <literal>Classpath</literal> domain object:
                    <sample id="partialOverwrites" dir="eclipse"
                            title="Partial Overwrite for Classpath">
                        <sourcefile file="build.gradle" snippet="module-before-merged"/>
                    </sample>
                    The resulting <literal>.classpath</literal> file will only contain Gradle-generated dependency entries, but
                    not any other dependency entries that may have been present in the original file. (In the case of dependency entries,
                    this is also the default behavior.) Other sections of the <literal>.classpath</literal> file will be either left as-is or merged.
                    The same could be done for the natures in the <literal>.project</literal> file:
                    <sample id="partialOverwritesProject" dir="eclipse"
                            title="Partial Overwrite for Project">
                        <sourcefile file="build.gradle" snippet="project-before-merged"/>
                    </sample>
                </para>
            </section>
            <section>
                <title>Modifying the fully populated domain objects</title>
                <para>The <code>whenMerged</code> hook allows to manipulate the fully populated domain objects. Often this is the
                    preferred way to customize Eclipse files. Here is how you would export all the dependencies of an Eclipse project:
                    <sample id="exportDependencies" dir="eclipse"
                            title="Export Dependencies">
                        <sourcefile file="build.gradle" snippet="module-when-merged"/>
                    </sample>
                </para>
            </section>
            <section>
                <title>Modifying the XML representation</title>
                <para>The <code>withXml</code>hook allows to manipulate the in-memory XML representation just before the file gets written to disk.
                    Although Groovy's XML support makes up for a lot, this approach is less convenient than manipulating the domain objects.
                    In return, you get total control over the generated file, including sections not modeled by the domain objects.
                    <sample id="wtpWithXml" dir="eclipse"
                            title="Customizing the XML">
                        <sourcefile file="build.gradle" snippet="wtp-with-xml"/>
                        <test args="cleanEclipse eclipse"/>
                    </sample>
                </para>
            </section>
        </section>
    </section>
</chapter>
