<!--
  ~ Copyright 2009 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='more_about_tasks'>
    <title>More about Tasks</title>
    <para>In the introductory tutorial (<xref linkend='tutorial_using_tasks'/>) you learned how to
        create simple tasks. You also learned how to add additional behavior to these tasks later on, and you 
        learned how to create dependencies between tasks. This was all about simple tasks, but Gradle takes the concept
        of tasks further. Gradle supports <firstterm>enhanced tasks</firstterm>, which are tasks that have their own
        properties and methods. This is really different from what you are used to with Ant targets. Such enhanced tasks are
        either provided by you or built into Gradle.
    </para>
    <section>
        <title>Defining tasks</title>
        <para>We have already seen how to define tasks using a keyword style in <xref linkend="tutorial_using_tasks"/>.
            There are a few variations on this style, which you may need to use in certain situations. For example,
            the keyword style does not work in expressions.
        </para>
        <sample id="defineAsExpression" dir="userguide/tasks/defineAsExpression" title="Defining tasks">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>You can also use strings for the task names:</para>
        <sample id="defineUsingStringTaskNames" dir="userguide/tasks/defineUsingStringTaskNames" title="Defining tasks - using strings for task names">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>There is an alternative syntax for defining tasks, which you may prefer to use:</para>
        <sample id="addToTaskContainer" dir="userguide/tasks/addToTaskContainer" title="Defining tasks with alternative syntax">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>Here we add tasks to the <literal>tasks</literal> collection. Have a look at
            <apilink class="org.gradle.api.tasks.TaskContainer"/> for more variations of the <literal>create()</literal>
            method.</para>
    </section>
    <section>
        <title>Locating tasks</title>
        <para>You often need to locate the tasks that you have defined in the build file, for example, to configure them
            or use them for dependencies. There are a number of ways of doing this. Firstly, each task is available as
            a property of the project, using the task name as the property name:
        </para>
        <sample id="accessAsProperty" dir="userguide/tasks/accessAsProperty" title="Accessing tasks as properties">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>Tasks are also available through the <literal>tasks</literal> collection.</para>
        <sample id="accessFromTaskContainer" dir="userguide/tasks/accessFromTaskContainer" title="Accessing tasks via tasks collection">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>You can access tasks from any project using the task's path using the <literal>tasks.getByPath()</literal>
            method. You can call the <literal>getByPath()</literal> method with a task name, or a relative path, or an
            absolute path.</para>
        <sample id="accessUsingPath" dir="userguide/tasks/accessUsingPath" title="Accessing tasks by path">
            <sourcefile file="build.gradle"/>
            <output args="-q hello"/>
        </sample>
        <para>Have a look at <apilink class="org.gradle.api.tasks.TaskContainer"/> for more options for locating tasks.</para>
    </section>
    <section id='sec:configuring_tasks'>
        <title>Configuring tasks</title>
        <para>As an example, let's look at the <classname>Copy</classname> task provided by Gradle. To create a
            <classname>Copy</classname> task for your build, you can declare in your build script:
        </para>
        <sample id="declareTask" dir="userguide/tasks/configureUsingClosure" title="Creating a copy task">
            <sourcefile file="build.gradle" snippet="declare-task"/>
        </sample>
        <para>This creates a copy task with no default behavior.
            The task can be configured using its API (see <apilink class="org.gradle.api.tasks.Copy"/>).
			The following examples show several different ways to achieve the same configuration.
        </para>
        <para>Just to be clear, realize that the name of this task is “<literal>myCopy</literal>”, but it is of
        <emphasis>type</emphasis> “<literal>Copy</literal>”.  You can have multiple tasks of the same
        <emphasis>type</emphasis>, but with different names. You'll find this gives you a lot of power to implement
        cross-cutting concerns across all tasks of a particular type.
        </para>
        <sample id="configureUsingVar" dir="userguide/tasks/configureUsingVar" title="Configuring a task - various ways">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>This is similar to the way we would configure objects in Java. You have to repeat the context
            (<literal>myCopy</literal>) in the configuration statement every time. This is a redundancy and not very
            nice to read.
        </para>
        <para>There is another way of configuring a task. It also preserves the context and it is arguably the
            most readable. It is usually our favorite.
        </para>
        <sample id="configureUsingClosure" dir="userguide/tasks/configureUsingClosure" title="Configuring a task - with closure">
            <sourcefile file="build.gradle"/>
        </sample>
        <para>This works for <emphasis>any</emphasis> task. Line 3 of the example is just a shortcut for the
            <literal>tasks.getByName()</literal> method. It is important to note that if you pass a closure to the
            <literal>getByName()</literal> method, this closure is applied to <emphasis>configure</emphasis> the task, not when
            the task executes.
        </para>
        <para>You can also use a configuration closure when you define a task.</para>
        <sample id="defineAndConfigure" dir="userguide/tasks/defineAndConfigure" title="Defining a task with closure">
            <sourcefile file="build.gradle" snippet="no-description"/>
        </sample>
        <tip>
            <title>Don't forget about the build phases</title>
            <para>A task has both configuration and actions.
                When using the <literal>&lt;&lt;</literal>, you are simply using a shortcut to define an action.
                Code defined in the configuration section of your task will get executed during the configuration phase of the build regardless of what task was targeted.
                See <xref linkend="build_lifecycle"/> for more details about the build lifecycle.
            </para>
        </tip>
    </section>
    <section id='sec:adding_dependencies_to_tasks'>
        <title>Adding dependencies to a task</title>
        <para>There are several ways you can define the dependencies of a task. In
            <xref linkend='sec:task_dependencies'/>
            you were introduced to defining dependencies using task names. Task names can refer to tasks in the same
            project as the task, or to tasks in other projects. To refer to a task in another project, you prefix the
            name of the task with the path of the project it belongs to. The following is an example which adds a dependency
            from
            <literal>projectA:taskX</literal>
            to
            <literal>projectB:taskY</literal>:
        </para>
        <sample id="addDependencyUsingPath" dir="userguide/tasks/addDependencyUsingPath" title="Adding dependency on task from another project">
            <sourcefile file="build.gradle"/>
            <output args="-q taskX"/>
        </sample>
        <para>Instead of using a task name, you can define a dependency using a
            <classname>Task</classname> object, as shown in this example:
        </para>
        <sample id="addDependencyUsingTask" dir="userguide/tasks/addDependencyUsingTask" title="Adding dependency using task object">
            <sourcefile file="build.gradle"/>
            <output args="-q taskX"/>
        </sample>
        <para>For more advanced uses, you can define a task dependency using a closure. When evaluated, the closure is
            passed the task whose dependencies are being calculated. The closure should return a single
            <classname>Task</classname> or collection of <classname>Task</classname> objects, which are then treated
            as dependencies of the task. The following example adds a dependency from <literal>taskX</literal>
            to all the tasks in the project whose name starts with <literal>lib</literal>:
        </para>
        <sample id="addDependencyUsingClosure" dir="userguide/tasks/addDependencyUsingClosure" title="Adding dependency using closure">
            <sourcefile file="build.gradle"/>
            <output args="-q taskX"/>
        </sample>
        <para>For more information about task dependencies, see the <apilink class="org.gradle.api.Task"/> API.</para>
    </section>
    <section id="sec:ordering_tasks">
        <title>Ordering tasks</title>
        <note>
            <para>
                Task ordering is an <link linkend="feature_lifecycle">incubating</link> feature. Please be aware that this feature may change in later Gradle versions.
            </para>
        </note>
        <para>
            In some cases it is useful to control the <emphasis>order</emphasis> in which 2 tasks will execute, without introducing an explicit dependency between those tasks.
            The primary difference between a task <emphasis>ordering</emphasis> and a task <emphasis>dependency</emphasis> is that an ordering rule does not influence which tasks
            will be executed, only the order in which they will be executed.
        </para>
        <para>
            Task ordering can be useful in a number of scenarios:
        </para>
        <itemizedlist>
            <listitem>Enforce sequential ordering of tasks: eg. 'build' never runs before 'clean'.</listitem>
            <listitem>Run build validations early in the build: eg. validate I have the correct credentials before starting the work for a release build.</listitem>
            <listitem>Get feedback faster by running quick verification tasks before long verification tasks: eg. unit tests should run before integration tests.</listitem>
            <listitem>A task that aggregates the results of all tasks of a particular type: eg. test report task combines the outputs of all executed test tasks.</listitem>
        </itemizedlist>
        <para>
            There are two ordering rules available: “<emphasis>must run after</emphasis>” and “<emphasis>should run after</emphasis>”.
        </para>
        <para>When you use the “must run after” ordering rule you specify that <literal>taskB</literal> must always
        run after <literal>taskA</literal>, whenever both <literal>taskA</literal> and <literal>taskB</literal> will
        be run. This is expressed as <literal>taskB.mustRunAfter(taskA)</literal>. The “should run
        after” ordering rule is similar but less strict as it will be ignored in two situations. Firstly if using
        that rule introduces an ordering cycle. Secondly when using parallel execution and all dependencies of a
        task have been satisfied apart from the “should run after” task, then this task will be run regardless of
        whether its “should run after” dependencies have been run or not. You should use “should run after”
        where the ordering is helpful but not strictly required.
        </para>
        <para>
            With these rules present it is still possible to execute <literal>taskA</literal> without <literal>taskB</literal> and vice-versa.
        </para>
        <sample id="mustRunAfter" dir="userguide/tasks/mustRunAfter" title="Adding a 'must run after' task ordering">
            <sourcefile file="build.gradle"/>
            <output args="-q taskY taskX"/>
        </sample>
        <sample id="shouldRunAfter" dir="userguide/tasks/shouldRunAfter" title="Adding a 'should run after' task ordering">
            <sourcefile file="build.gradle"/>
            <output args="-q taskY taskX"/>
        </sample>
        <para>In the examples above, it is still possible to execute <literal>taskY</literal> without causing <literal>taskX</literal> to run:</para>
        <sample id="mustRunAfterSingleTask" dir="userguide/tasks/mustRunAfter" title="Task ordering does not imply task execution">
            <output args="-q taskY"/>
        </sample>
        <para>To specify a “must run after” or “should run after” ordering between 2 tasks, you use the <apilink class="org.gradle.api.Task" method="mustRunAfter"/> and <apilink class="org.gradle.api.Task" method="shouldRunAfter"/> methods.
            These methods accept a task instance, a task name or any other input accepted by <apilink class="org.gradle.api.Task" method="dependsOn"/>.
        </para>
        <para>
            Note that “<literal>B.mustRunAfter(A)</literal>” or “<literal>B.shouldRunAfter(A)</literal>” does not imply any execution dependency between the tasks:
        </para>
        <itemizedlist>
            <listitem>It is possible to execute tasks <literal>A</literal> and <literal>B</literal> independently. The ordering rule only has an effect when both tasks are scheduled for execution.</listitem>
            <listitem>When run with <literal>--continue</literal>, it is possible for <literal>B</literal> to execute in the event that <literal>A</literal> fails.</listitem>
        </itemizedlist>
        <para>As mentioned before, the “should run after” ordering rule will be ignored if it introduces an ordering cycle:</para>
        <sample id="shouldRunAfterWithCycle" dir="userguide/tasks/shouldRunAfterWithCycle" title="A 'should run after' task ordering is ignored if it introduces an ordering cycle">
            <sourcefile file="build.gradle"/>
            <output args="-q taskX"/>
        </sample>
    </section>
    <section>
        <title>Adding a description to a task</title>
        <para>You can add a description to your task. This description is displayed when executing
            <userinput>gradle tasks</userinput>.
        </para>
        <sample id="describeTask" dir="userguide/tasks/defineAndConfigure" title="Adding a description to a task">
            <sourcefile file="build.gradle"/>
        </sample>
    </section>
    <section>
        <title>Replacing tasks</title>
        <para>Sometimes you want to replace a task. For example, if you want to exchange a task added by the Java plugin
            with a custom task of a different type. You can achieve this with:
        </para>
        <sample id="replaceTask" dir="userguide/tutorial/replaceTask" title="Overwriting a task">
            <sourcefile file="build.gradle"/>
            <output args="-q copy"/>
        </sample>
        <para>This will replace a task of type <literal>Copy</literal> with the task you've defined, because it
        uses the same name. When you define the new task, you have to set the <literal>overwrite</literal> property
        to true. Otherwise Gradle throws an exception, saying that a task with that name already exists.
        </para>
    </section>
    <section>
        <title>Skipping tasks</title>
        <para>Gradle offers multiple ways to skip the execution of a task.</para>

        <section>
            <title>Using a predicate</title>
            <para>You can use the <literal>onlyIf()</literal> method to attach a predicate to a task. The task's
                actions are only executed if the predicate evaluates to true. You implement the predicate as a closure.
                The closure is passed the task as a parameter, and should return true if the task should execute
                and false if the task should be skipped. The predicate is evaluated just before the task is due
                to be executed.
                </para>
            <sample id="taskOnlyIf" dir="userguide/tutorial/taskOnlyIf" title="Skipping a task using a predicate">
                <sourcefile file="build.gradle"/>
                <output args="hello -PskipHello"/>
            </sample>
        </section>

        <section>
        <title>Using StopExecutionException</title>
        <para>If the logic for skipping a task can't be expressed with a predicate, you can use the
            <apilink class="org.gradle.api.tasks.StopExecutionException"/>. If this exception is thrown by an action,
            the further execution of this action as well as the execution of
            any following action of this task is skipped. The build continues with executing the next task.
        </para>
        <sample id="stopExecutionException" dir="userguide/tutorial/stopExecutionException" title="Skipping tasks with StopExecutionException">
            <sourcefile file="build.gradle"/>
            <output args="-q myTask"/>
        </sample>
        <para>This feature is helpful if you work with tasks provided by Gradle. It allows you to add
            <emphasis>conditional</emphasis> execution of the built-in actions of such a task.
            <footnote>
                <para>You might be wondering why there is neither an import for the
                    <literal>StopExecutionException</literal>
                    nor do we access it via its fully qualified name. The reason is, that Gradle adds a set of default imports
                    to your script (see <xref linkend='script-default-imports'/>).
                </para>
            </footnote>
        </para>
        </section>

        <section>
        <title>Enabling and disabling tasks</title>
        <para>Every task has an <literal>enabled</literal>
            flag which defaults to <literal>true</literal>. Setting it to <literal>false</literal> prevents the
            execution of any of the task's actions.
        </para>
        <sample id="disableTask" dir="userguide/tutorial/disableTask" title="Enabling and disabling tasks">
            <sourcefile file="build.gradle"/>
            <output args="disableMe"/>
        </sample>
        </section>
    </section>

    <section id="sec:up_to_date_checks">
        <title>Skipping tasks that are up-to-date</title>
        <para>If you are using one of the tasks that come with Gradle, such as a task added by the Java plugin,
            you might have noticed that Gradle will skip tasks that are up-to-date. This behaviour is also available
            for your tasks, not just for built-in tasks.
        </para>
        <section id="sec:task_inputs_outputs">
            <title>Declaring a task's inputs and outputs</title>
            <para>
                Let's have a look at an example. Here our task generates several output files from a source XML file. Let's
                run it a couple of times.
            </para>
            <sample id="generatorTask" dir="userguide/tasks/incrementalBuild/noInputsAndOutputs" title="A generator task">
                <sourcefile file="build.gradle"/>
                <output args="transform" ignoreExtraLines="true"/>
                <output args="transform" ignoreExtraLines="true"/>
            </sample>
            <para>Notice that Gradle executes this task a second time, and does not skip the task even though nothing has
                changed. Our example task was defined using an action closure. Gradle has no idea what the closure does and
                cannot automatically figure out whether the task is up-to-date or not. To use Gradle's up-to-date checking,
                you need to declare the inputs and outputs of the task.
            </para>
            <para>Each task has an <literal>inputs</literal> and <literal>outputs</literal> property, which you use to
                declare the inputs and outputs of the task. Below, we have changed our example to declare that it takes
                the source XML file as an input and produces output to a destination directory. Let's run it a couple
                of times.
            </para>
            <sample id="incrementalTask" dir="userguide/tasks/incrementalBuild/inputsAndOutputs" title="Declaring the inputs and outputs of a task">
                <sourcefile file="build.gradle"/>
                <output args="transform" outputFile="generatorTask.out" ignoreExtraLines="true"/>
                <output args="transform" ignoreExtraLines="true"/>
            </sample>
            <para>Now, Gradle knows which files to check to determine whether the task is up-to-date or not.</para>
            <para>
                The task's <literal>inputs</literal> property is of type <apilink class="org.gradle.api.tasks.TaskInputs"/>.
                The task's <literal>outputs</literal> property is of type <apilink class="org.gradle.api.tasks.TaskOutputs"/>.
            </para>
            <para>
                A task with no defined outputs will <emphasis>never</emphasis> be considered up-to-date.
                For scenarios where the outputs of a task are not files, or for more complex scenarios, the
                <apilink class="org.gradle.api.tasks.TaskOutputs" method="upToDateWhen(groovy.lang.Closure)" /> method allows you to calculate programmatically if
                the tasks outputs should be considered up to date.
            </para>
            <para>
                A task with only outputs defined will be considered up-to-date if those outputs are unchanged since the previous build.
            </para>

        </section>
        <section>
            <title>How does it work?</title>
            <para>
                Before a task is executed for the first time, Gradle takes a snapshot of the inputs. This snapshot contains
                the set of input files and a hash of the contents of each file. Gradle then executes the task. If the
                task completes successfully, Gradle takes a snapshot of the outputs. This snapshot contains the set of
                output files and a hash of the contents of each file. Gradle persists both snapshots for the next time the task
                is executed.
            </para>
            <para>
                Each time after that, before the task is executed, Gradle takes a new snapshot of the inputs and outputs.
                If the new snapshots are the same as the previous snapshots, Gradle assumes that the outputs are up to
                date and skips the task. If they are not the same, Gradle executes the task. Gradle persists both snapshots
                for the next time the task is executed.
            </para>
            <para>
                Note that if a task has an output directory specified, any files added to that directory since the last time it was executed
                are ignored and will NOT cause the task to be out of date. This is so unrelated tasks may share an output directory without interfering with each other.
                If this is not the behaviour you want for some reason, consider using <apilink class="org.gradle.api.tasks.TaskOutputs" method="upToDateWhen(groovy.lang.Closure)" />
            </para>
        </section>
    </section>

    <section>
        <title>Task rules</title>
        <para>Sometimes you want to have a task whose behavior depends on a large or infinite number value range
            of parameters. A very nice and expressive way to provide such tasks are task rules:
        </para>
        <sample id="taskRule" dir="userguide/tasks/addRules" title="Task rule">
            <sourcefile file="build.gradle" snippet="task-rule"/>
            <output args="-q pingServer1"/>
        </sample>
        <para>The String parameter is used as a description for the rule, which is shown with <userinput>gradle tasks</userinput>.
        </para>
        <para>Rules are not only used when calling tasks from the command line. You can also create dependsOn relations
            on rule based tasks:
        </para>
        <sample id="taskRuleDependsOn" dir="userguide/tasks/addRules" title="Dependency on rule based tasks">
            <sourcefile file="build.gradle"/>
            <output args="-q groupPing"/>
        </sample>
        <para>If you run “<literal>gradle -q tasks</literal>” you won't find a task named
        “<literal>pingServer1</literal>” or “<literal>pingServer2</literal>”, but this script is executing logic
        based on the request to run those tasks.</para>
    </section>

    <section>
        <title>Finalizer tasks</title>
        <note>
            <para>
                Finalizers tasks are an <firstterm>incubating</firstterm> feature (see <xref linkend="sec:incubating_state"/>).
            </para>
        </note>
        <para>Finalizer tasks are automatically added to the task graph when the finalized task is scheduled to run.</para>
        <sample id="taskFinalizers" dir="userguide/tasks/finalizers" title="Adding a task finalizer">
            <sourcefile file="build.gradle"/>
            <output args="-q taskX"/>
        </sample>
        <para>Finalizer tasks will be executed even if the finalized task fails.</para>
        <sample id="taskFinalizersWithFailure" dir="userguide/tasks/finalizersWithFailure" title="Task finalizer for a failing task">
            <sourcefile file="build.gradle"/>
            <output args="-q taskX"/>
        </sample>
        <para>On the other hand, finalizer tasks are not executed if the finalized task didn't do any work, for example if it
        is considered up to date or if a dependent task fails.</para>
        <para>Finalizer tasks are useful in situations where the build creates a resource that has to be cleaned up regardless
            of the build failing or succeeding. An example of such a resource is a web container that is started before an integration test task
            and which should be always shut down, even if some of the tests fail.</para>
        <para>To specify a finalizer task you use the <apilink class="org.gradle.api.Task" method="finalizedBy"/> method.
            This method accepts a task instance, a task name, or any other input accepted by <apilink class="org.gradle.api.Task" method="dependsOn"/>.
        </para>
    </section>

    <section id='sec:the_idea_behind_gradle_tasks'>
        <title>Summary</title>
        <para>If you are coming from Ant, an enhanced Gradle task like <emphasis>Copy</emphasis> seems like a cross
            between an Ant target and an Ant task. Although Ant's tasks and targets are really different entities,
            Gradle combines these notions into a single entity. Simple Gradle tasks are like Ant's targets, but enhanced
            Gradle tasks also include aspects of Ant tasks. All of Gradle's tasks share a common API and you can create
            dependencies between them. These tasks are much easier to configure than an Ant task.
            They make full use of the type system, and are more expressive and easier to maintain.
        </para>
    </section>
</chapter>
