// Copyright 2018 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.

[[working_with_dependencies]]
= Working with Dependencies

Gradle provides an extensive API for navigating, inspecting and post-processing metadata and artifacts of resolved dependencies.

The main entry point for this functionality is the link:{groovyDslPath}/org.gradle.api.artifacts.Configuration.html[Configuration] API. To learn more about the fundamentals of configurations, see <<managing_dependency_configurations.adoc#managing_dependency_configurations,Managing Dependency Configurations>>.

== Iterating over dependencies assigned to a configuration

Sometimes you'll want to implement logic based on the dependencies declared in the build script of a project e.g. to inspect them in a Gradle plugin. You can iterate over the set of dependencies assigned to a configuration with the help of the method link:{groovyDslPath}/org.gradle.api.artifacts.Configuration.html#org.gradle.api.artifacts.Configuration:dependencies[Configuration.getDependencies()]. Alternatively, you can also use link:{groovyDslPath}/org.gradle.api.artifacts.Configuration.html#org.gradle.api.artifacts.Configuration:allDependencies[Configuration.getAllDependencies()] to include the dependencies declared in <<managing_dependency_configurations.adoc#sub:inheriting_dependencies_from_other_configurations,superconfigurations>>. These APIs only return the declared dependencies and do not trigger <<introduction_dependency_management.adoc#sec:dependency_resolution,dependency resolution>>. Therefore, the dependency sets do not include transitive dependencies. Calling the APIs during the <<build_lifecycle.adoc#sec:build_phases,configuration phase of the build lifecycle>> does not result in a significant performance impact.

.Iterating over the dependencies assigned to a configuration
====
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/iterateDependencies/groovy",files="build.gradle[tags=iteration-task]"]
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/iterateDependencies/kotlin",files="build.gradle.kts[tags=iteration-task]"]
====


== Iterating over artifacts resolved for a module

None of the <<inspecting_dependencies.adoc#inspecting_dependencies,dependency reporting>> helps you with inspecting or further processing the underlying, resolved artifacts of a module. A typical use case for accessing the artifacts is to copy them into a specific directory or filter out files of interest based on a specific file extension.

You can iterate over the complete set of artifacts resolved for a module with the help of the method link:{javadocPath}/org/gradle/api/file/FileCollection.html#getFiles--[FileCollection.getFiles()]. Every file instance returned from the method points to its location in the <<dependency_cache.adoc#dependency_cache,dependency cache>>. Using this method on a `Configuration` instance is possible as the interface extends `FileCollection`.

.Iterating over the artifacts resolved for a module
====
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/iterateArtifacts/groovy",files="build.gradle[tags=iteration-task]"]
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/iterateArtifacts/kotlin",files="build.gradle.kts[tags=iteration-task]"]
====

[NOTE]
====
Iterating over the artifacts of a module automatically resolves the configuration. A resolved configuration becomes immutable and cannot add or remove dependencies. If needed you can copy a configuration for further modification via link:{groovyDslPath}/org.gradle.api.artifacts.Configuration.html#org.gradle.api.artifacts.Configuration:copy()[Configuration.copy()].
====

== Navigating the dependency graph

As a plugin developer, you may want to navigate the full graph of dependencies assigned to a configuration e.g. for turning the dependency graph into a visualization. You can access the full graph of dependencies for a configuration with the help of the link:{javadocPath}/org/gradle/api/artifacts/result/ResolutionResult.html[ResolutionResult].

The resolution result provides various methods for accessing the resolved and unresolved dependencies. For demonstration purposes the sample code uses link:{javadocPath}/org/gradle/api/artifacts/result/ResolutionResult.html#getRoot--[ResolutionResult.getRoot()] to access the root node the resolved dependency graph. Each dependency of this component returns an instance of link:{javadocPath}/org/gradle/api/artifacts/result/ResolvedDependencyResult.html[ResolvedDependencyResult] or link:{javadocPath}/org/gradle/api/artifacts/result/UnresolvedDependencyResult.html[UnresolvedDependencyResult] providing detailed information about the node.

.Walking the resolved and unresolved dependencies of a configuration
====
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/walkGraph/groovy",files="build.gradle[tags=walk-task]"]
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/walkGraph/kotlin",files="build.gradle.kts[tags=walk-task]"]
====

== Accessing a module’s metadata file

As part of the dependency resolution process, Gradle downloads the metadata file of a module and stores it in the dependency cache. Some organizations enforce strong restrictions on accessing repositories outside of internal network. Instead of downloading artifacts, those organizations prefer to provide an "installable" Gradle cache with all artifacts contained in it to fulfill the build's dependency requirements.

The artifact query API provides access to the raw files of a module. Currently, it allows getting a handle to the metadata file and some selected, additional artifacts (e.g. a JVM-based module's source and Javadoc files). The main API entry point is link:{groovyDslPath}/org.gradle.api.artifacts.query.ArtifactResolutionQuery.html[ArtifactResolutionQuery].

Let's say you wanted to post-process the metadata file of a Maven module. The group, name and version of the module component serve as input to the artifact resolution query. After executing the query, you get a handle to all components that match the criteria and their underlying files. Additionally, it's very easy to post-process the metadata file. The example code uses Groovy's link:https://docs.groovy-lang.org/latest/html/api/groovy/util/XmlSlurper.html[XmlSlurper] to ask for POM element values.

.Accessing a Maven module's metadata artifact

====
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/accessMetadataArtifact/groovy",files="build.gradle[tags=accessing-metadata-artifact]"]
include::sample[dir="userguide/dependencyManagement/workingWithDependencies/accessMetadataArtifact/kotlin",files="build.gradle.kts[tags=accessing-metadata-artifact]"]
====
