This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 5d139bdd127a62ee3fc4e725a0eaaebf12cdb928
Author: Guillaume Nodet <gno...@gmail.com>
AuthorDate: Thu Jun 6 16:24:08 2024 +0200

    [MNG-8151] Merge DependencyCollector into DependencyResolver
---
 .../src/main/java/org/apache/maven/api/Node.java   |   2 +-
 .../main/java/org/apache/maven/api/Session.java    |  18 +-
 .../maven/api/services/DependencyCollector.java    | 107 -------
 .../api/services/DependencyCollectorException.java |  43 ---
 .../api/services/DependencyCollectorRequest.java   | 310 ---------------------
 .../api/services/DependencyCollectorResult.java    |  51 ----
 .../maven/api/services/DependencyResolver.java     | 147 ++++++++--
 .../api/services/DependencyResolverRequest.java    | 291 +++++++++++++++----
 .../api/services/DependencyResolverResult.java     |  25 +-
 .../maven/api/services/ProjectBuilderResult.java   |   2 +-
 .../maven/internal/impl/AbstractSession.java       |  28 +-
 .../internal/impl/DefaultDependencyCollector.java  | 109 --------
 .../internal/impl/DefaultDependencyResolver.java   | 182 ++++++++++++
 .../impl/DefaultDependencyResolverResult.java      |  11 +-
 .../maven/internal/impl/standalone/ApiRunner.java  |   2 +-
 .../internal/impl/DefaultDependencyResolver.java   | 110 --------
 .../maven/internal/impl/DefaultProjectBuilder.java |  18 +-
 .../META-INF/maven/org.apache.maven.api.di.Inject  |   2 +-
 18 files changed, 621 insertions(+), 837 deletions(-)

diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java 
b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java
index 4d41444109..247cc47983 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java
@@ -33,7 +33,7 @@ import org.apache.maven.api.annotations.Provider;
  * Represents a dependency node within a Maven project's dependency collector.
  *
  * @since 4.0.0
- * @see org.apache.maven.api.services.DependencyCollectorResult#getRoot()
+ * @see org.apache.maven.api.services.DependencyResolverResult#getRoot()
  */
 @Experimental
 @Immutable
diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java 
b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
index 31aeb06b7b..720bb85e47 100644
--- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
+++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java
@@ -496,25 +496,25 @@ public interface Session {
     boolean isVersionSnapshot(@Nonnull String version);
 
     /**
-     * Shortcut for {@code getService(DependencyCollector.class).collect(...)}
+     * Shortcut for {@code getService(DependencyResolver.class).collect(...)}
      *
      * @param artifact artifact for which to get the dependencies, including 
transitive ones
      * @return root node of the dependency graph for the given artifact
      *
-     * @see org.apache.maven.api.services.DependencyCollector#collect(Session, 
Artifact)
-     * @throws org.apache.maven.api.services.DependencyCollectorException if 
the dependency collection failed
+     * @see org.apache.maven.api.services.DependencyResolver#collect(Session, 
Artifact)
+     * @throws org.apache.maven.api.services.DependencyResolverException if 
the dependency collection failed
      */
     @Nonnull
     Node collectDependencies(@Nonnull Artifact artifact);
 
     /**
-     * Shortcut for {@code getService(DependencyCollector.class).collect(...)}
+     * Shortcut for {@code getService(DependencyResolver.class).collect(...)}
      *
      * @param project project for which to get the dependencies, including 
transitive ones
      * @return root node of the dependency graph for the given project
      *
-     * @see org.apache.maven.api.services.DependencyCollector#collect(Session, 
Project)
-     * @throws org.apache.maven.api.services.DependencyCollectorException if 
the dependency collection failed
+     * @see org.apache.maven.api.services.DependencyResolver#collect(Session, 
Project)
+     * @throws org.apache.maven.api.services.DependencyResolverException if 
the dependency collection failed
      */
     @Nonnull
     Node collectDependencies(@Nonnull Project project);
@@ -524,13 +524,13 @@ public interface Session {
      * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
      * artifact files.
      * <p>
-     * Shortcut for {@code getService(DependencyCollector.class).resolve(...)}
+     * Shortcut for {@code getService(DependencyResolver.class).resolve(...)}
      *
      * @param dependency dependency for which to get transitive dependencies
      * @return root node of the dependency graph for the given artifact
      *
-     * @see org.apache.maven.api.services.DependencyCollector#collect(Session, 
DependencyCoordinate)
-     * @throws org.apache.maven.api.services.DependencyCollectorException if 
the dependency collection failed
+     * @see org.apache.maven.api.services.DependencyResolver#collect(Session, 
DependencyCoordinate)
+     * @throws org.apache.maven.api.services.DependencyResolverException if 
the dependency collection failed
      */
     @Nonnull
     Node collectDependencies(@Nonnull DependencyCoordinate dependency);
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java
deleted file mode 100644
index 788fd67c8c..0000000000
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.maven.api.services;
-
-import org.apache.maven.api.Artifact;
-import org.apache.maven.api.DependencyCoordinate;
-import org.apache.maven.api.Project;
-import org.apache.maven.api.Service;
-import org.apache.maven.api.Session;
-import org.apache.maven.api.annotations.Experimental;
-import org.apache.maven.api.annotations.Nonnull;
-
-/**
- * The DependencyCollector service can be used to collect dependencies
- * for a given artifact and builds a graph of them.
- * The dependencies collection mechanism will not download any artifacts,
- * and only the pom files will be downloaded.
- *
- * @since 4.0.0
- */
-@Experimental
-public interface DependencyCollector extends Service {
-
-    /**
-     * Collects the transitive dependencies and builds a dependency graph.
-     * Note that this operation is only concerned about determining the 
coordinates of the
-     * transitive dependencies and does not actually resolve the artifact 
files.
-     *
-     * @param request the dependency collection request, must not be {@code 
null}
-     * @return the collection result, never {@code null}
-     * @throws DependencyCollectorException if the dependency tree could not 
be built
-     * @throws IllegalArgumentException if an argument is null or invalid
-     *
-     * @see DependencyCollector#collect(Session, Project)
-     * @see DependencyCollector#collect(Session, DependencyCoordinate)
-     * @see DependencyCollector#collect(Session, Artifact)
-     */
-    @Nonnull
-    DependencyCollectorResult collect(@Nonnull DependencyCollectorRequest 
request);
-
-    /**
-     * Collects the transitive dependencies of some artifacts and builds a 
dependency graph. Note that this operation is
-     * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
-     * artifact files.
-     *
-     * @param session the {@link Session}, must not be {@code null}
-     * @param root the Maven Dependency, must not be {@code null}
-     * @return the collection result, never {@code null}
-     * @throws DependencyCollectorException if the dependency tree could not 
be built
-     * @throws IllegalArgumentException if an argument is null or invalid
-     * @see #collect(DependencyCollectorRequest)
-     */
-    @Nonnull
-    default DependencyCollectorResult collect(@Nonnull Session session, 
@Nonnull DependencyCoordinate root) {
-        return collect(DependencyCollectorRequest.build(session, root));
-    }
-
-    /**
-     * Collects the transitive dependencies of some artifacts and builds a 
dependency graph. Note that this operation is
-     * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
-     * artifact files.
-     *
-     * @param session the {@link Session}, must not be {@code null}
-     * @param project the {@link Project}, must not be {@code null}
-     * @return the collection result, never {@code null}
-     * @throws DependencyCollectorException if the dependency tree could not 
be built
-     * @throws IllegalArgumentException if an argument is null or invalid
-     * @see #collect(DependencyCollectorRequest)
-     */
-    @Nonnull
-    default DependencyCollectorResult collect(@Nonnull Session session, 
@Nonnull Project project) {
-        return collect(DependencyCollectorRequest.build(session, project));
-    }
-
-    /**
-     * Collects the transitive dependencies of some artifacts and builds a 
dependency graph. Note that this operation is
-     * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
-     * artifact files.
-     *
-     * @param session the {@link Session}, must not be {@code null}
-     * @param artifact the {@link Artifact}, must not be {@code null}
-     * @return the collection result, never {@code null}
-     * @throws DependencyCollectorException if the dependency tree could not 
be built
-     * @throws IllegalArgumentException if an argument is null or invalid
-     * @see #collect(DependencyCollectorRequest)
-     */
-    @Nonnull
-    default DependencyCollectorResult collect(@Nonnull Session session, 
@Nonnull Artifact artifact) {
-        return collect(DependencyCollectorRequest.build(session, artifact));
-    }
-}
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java
deleted file mode 100644
index 466c40ec9b..0000000000
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.maven.api.services;
-
-import org.apache.maven.api.annotations.Experimental;
-
-/**
- * Thrown in case of bad artifact descriptors, version ranges or other
- * issues encountered during calculation of the dependency graph.
- *
- * @since 4.0.0
- */
-@Experimental
-public class DependencyCollectorException extends MavenException {
-    /**
-     *
-     */
-    private static final long serialVersionUID = -3134726259840210686L;
-
-    /**
-     * @param message the message you would give for the exception
-     * @param cause the cause which is related to the message
-     */
-    public DependencyCollectorException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java
deleted file mode 100644
index ebaa10b09e..0000000000
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.maven.api.services;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
-import org.apache.maven.api.Artifact;
-import org.apache.maven.api.DependencyCoordinate;
-import org.apache.maven.api.Project;
-import org.apache.maven.api.Session;
-import org.apache.maven.api.annotations.Experimental;
-import org.apache.maven.api.annotations.Immutable;
-import org.apache.maven.api.annotations.Nonnull;
-import org.apache.maven.api.annotations.NotThreadSafe;
-import org.apache.maven.api.annotations.Nullable;
-
-import static org.apache.maven.api.services.BaseRequest.nonNull;
-
-/**
- * A request to collect the transitive dependencies and to build a dependency 
graph from them. There are three ways to
- * create a dependency graph. First, only the root dependency can be given. 
Second, a root dependency and direct
- * dependencies can be specified in which case the specified direct 
dependencies are merged with the direct dependencies
- * retrieved from the artifact descriptor of the root dependency. And last, 
only direct dependencies can be specified in
- * which case the root node of the resulting graph has no associated 
dependency.
- *
- * @since 4.0.0
- * @see DependencyCollector#collect(DependencyCollectorRequest)
- */
-@Experimental
-@Immutable
-public interface DependencyCollectorRequest {
-
-    @Nonnull
-    Session getSession();
-
-    Optional<Project> getProject();
-
-    @Nonnull
-    Optional<Artifact> getRootArtifact();
-
-    @Nonnull
-    Optional<DependencyCoordinate> getRoot();
-
-    @Nonnull
-    Collection<DependencyCoordinate> getDependencies();
-
-    @Nonnull
-    Collection<DependencyCoordinate> getManagedDependencies();
-
-    boolean getVerbose();
-
-    @Nonnull
-    static DependencyCollectorRequest build(@Nonnull Session session, Artifact 
root) {
-        return builder()
-                .session(nonNull(session, "session cannot be null"))
-                .rootArtifact(nonNull(root, "root cannot be null"))
-                .build();
-    }
-
-    @Nonnull
-    static DependencyCollectorRequest build(@Nonnull Session session, @Nonnull 
DependencyCoordinate root) {
-        return builder()
-                .session(nonNull(session, "session cannot be null"))
-                .root(nonNull(root, "root cannot be null"))
-                .build();
-    }
-
-    @Nonnull
-    static DependencyCollectorRequest build(@Nonnull Session session, @Nonnull 
Project project) {
-        return builder()
-                .session(nonNull(session, "session cannot be null"))
-                .project(nonNull(project, "project cannot be null"))
-                .build();
-    }
-
-    @Nonnull
-    static DependencyCollectorRequestBuilder builder() {
-        return new DependencyCollectorRequestBuilder();
-    }
-
-    @NotThreadSafe
-    class DependencyCollectorRequestBuilder {
-
-        Session session;
-        Project project;
-        Artifact rootArtifact;
-        DependencyCoordinate root;
-        List<DependencyCoordinate> dependencies = Collections.emptyList();
-        List<DependencyCoordinate> managedDependencies = 
Collections.emptyList();
-        boolean verbose;
-
-        DependencyCollectorRequestBuilder() {}
-
-        @Nonnull
-        public DependencyCollectorRequestBuilder session(@Nonnull Session 
session) {
-            this.session = session;
-            return this;
-        }
-
-        @Nonnull
-        public DependencyCollectorRequestBuilder project(@Nullable Project 
project) {
-            this.project = project;
-            return this;
-        }
-
-        /**
-         * Sets the root artifact for the dependency graph.
-         * This must not be confused with {@link #root(DependencyCoordinate)}: 
The root <em>dependency</em>, like any
-         * other specified dependency, will be subject to dependency 
collection/resolution, i.e. should have an artifact
-         * descriptor and a corresponding artifact file. The root 
<em>artifact</em> on the other hand is only used
-         * as a label for the root node of the graph in case no root 
dependency was specified. As such, the configured
-         * root artifact is ignored if {@link #root(DependencyCoordinate)} has 
been set.
-         *
-         * @param rootArtifact the root artifact for the dependency graph, may 
be {@code null}
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder rootArtifact(@Nullable 
Artifact rootArtifact) {
-            this.rootArtifact = rootArtifact;
-            return this;
-        }
-
-        /**
-         * @param root The root dependency
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder root(@Nonnull 
DependencyCoordinate root) {
-            this.root = root;
-            return this;
-        }
-
-        /**
-         * Sets the direct dependencies. If both a root dependency and direct 
dependencies are given in the request, the
-         * direct dependencies from the request will be merged with the direct 
dependencies from the root dependency's
-         * artifact descriptor, giving higher priority to the dependencies 
from the request.
-         *
-         * @param dependencies the direct dependencies, may be {@code null}
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder dependencies(@Nullable 
List<DependencyCoordinate> dependencies) {
-            this.dependencies = (dependencies != null) ? dependencies : 
Collections.emptyList();
-            return this;
-        }
-
-        /**
-         * Adds the specified direct dependency.
-         *
-         * @param dependency the dependency to add, may be {@code null}
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder dependency(@Nullable 
DependencyCoordinate dependency) {
-            if (dependency != null) {
-                if (this.dependencies.isEmpty()) {
-                    this.dependencies = new ArrayList<>();
-                }
-                this.dependencies.add(dependency);
-            }
-            return this;
-        }
-
-        /**
-         * Sets the dependency management to apply to transitive dependencies. 
To clarify, this management does not
-         * apply to
-         * the direct dependencies of the root node.
-         *
-         * @param managedDependencies the dependency management, may be {@code 
null}
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder managedDependencies(
-                @Nullable List<DependencyCoordinate> managedDependencies) {
-            this.managedDependencies = (managedDependencies != null) ? 
managedDependencies : Collections.emptyList();
-            return this;
-        }
-
-        /**
-         * Adds the specified managed dependency.
-         *
-         * @param managedDependency The managed dependency to add, may be 
{@code null} in which case the call
-         *                          will have no effect.
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder managedDependency(@Nullable 
DependencyCoordinate managedDependency) {
-            if (managedDependency != null) {
-                if (this.managedDependencies.isEmpty()) {
-                    this.managedDependencies = new ArrayList<>();
-                }
-                this.managedDependencies.add(managedDependency);
-            }
-            return this;
-        }
-
-        /**
-         * Specifies that the collection should be verbose.
-         *
-         * @param verbose whether the collection should be verbose or not
-         * @return this request for chaining, never {@code null}
-         */
-        @Nonnull
-        public DependencyCollectorRequestBuilder verbose(boolean verbose) {
-            this.verbose = verbose;
-            return this;
-        }
-
-        @Nonnull
-        public DependencyCollectorRequest build() {
-            return new DefaultDependencyCollectorRequest(
-                    session, project, rootArtifact, root, dependencies, 
managedDependencies, verbose);
-        }
-
-        static class DefaultDependencyCollectorRequest extends BaseRequest 
implements DependencyCollectorRequest {
-            private final Project project;
-            private final Artifact rootArtifact;
-            private final DependencyCoordinate root;
-            private final Collection<DependencyCoordinate> dependencies;
-            private final Collection<DependencyCoordinate> managedDependencies;
-            private final boolean verbose;
-
-            /**
-             * Creates a request with the specified properties.
-             *
-             * @param session      {@link Session}
-             * @param rootArtifact The root dependency whose transitive 
dependencies should be collected, may be {@code
-             *                     null}.
-             */
-            DefaultDependencyCollectorRequest(
-                    @Nonnull Session session,
-                    @Nullable Project project,
-                    @Nullable Artifact rootArtifact,
-                    @Nullable DependencyCoordinate root,
-                    @Nonnull Collection<DependencyCoordinate> dependencies,
-                    @Nonnull Collection<DependencyCoordinate> 
managedDependencies,
-                    boolean verbose) {
-                super(session);
-                this.project = project;
-                this.rootArtifact = rootArtifact;
-                this.root = root;
-                this.dependencies = unmodifiable(nonNull(dependencies, 
"dependencies cannot be null"));
-                this.managedDependencies =
-                        unmodifiable(nonNull(managedDependencies, 
"managedDependencies cannot be null"));
-                this.verbose = verbose;
-            }
-
-            @Nonnull
-            @Override
-            public Optional<Project> getProject() {
-                return Optional.ofNullable(project);
-            }
-
-            @Nonnull
-            @Override
-            public Optional<Artifact> getRootArtifact() {
-                return Optional.ofNullable(rootArtifact);
-            }
-
-            @Nonnull
-            @Override
-            public Optional<DependencyCoordinate> getRoot() {
-                return Optional.ofNullable(root);
-            }
-
-            @Nonnull
-            @Override
-            public Collection<DependencyCoordinate> getDependencies() {
-                return dependencies;
-            }
-
-            @Nonnull
-            @Override
-            public Collection<DependencyCoordinate> getManagedDependencies() {
-                return managedDependencies;
-            }
-
-            @Override
-            public boolean getVerbose() {
-                return verbose;
-            }
-
-            @Nonnull
-            @Override
-            public String toString() {
-                return getRoot() + " -> " + getDependencies();
-            }
-        }
-    }
-}
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java
deleted file mode 100644
index 77b6350390..0000000000
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.maven.api.services;
-
-import java.util.List;
-
-import org.apache.maven.api.Node;
-import org.apache.maven.api.annotations.Experimental;
-import org.apache.maven.api.annotations.Nonnull;
-import org.apache.maven.api.annotations.Nullable;
-
-/**
- * The result of a dependency collection request.
- *
- * @since 4.0.0
- * @see DependencyCollector#collect(DependencyCollectorRequest)
- */
-@Experimental
-public interface DependencyCollectorResult {
-    /**
-     * Gets the exceptions that occurred while building the dependency graph.
-     *
-     * @return the exceptions that occurred, never {@code null}
-     */
-    @Nonnull
-    List<Exception> getExceptions();
-
-    /**
-     * Gets the root node of the dependency graph.
-     *
-     * @return the root node of the dependency graph or {@code null} if none
-     */
-    @Nullable
-    Node getRoot();
-}
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java
index 9fefbc4cda..95feaa1925 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java
@@ -20,6 +20,7 @@ package org.apache.maven.api.services;
 
 import java.util.List;
 
+import org.apache.maven.api.Artifact;
 import org.apache.maven.api.DependencyCoordinate;
 import org.apache.maven.api.Node;
 import org.apache.maven.api.PathScope;
@@ -35,55 +36,165 @@ import org.apache.maven.api.annotations.Nonnull;
 @Experimental
 public interface DependencyResolver extends Service {
 
-    List<Node> flatten(Session session, Node node, PathScope scope) throws 
DependencyResolverException;
+    /**
+     * Collects the transitive dependencies of some artifacts and builds a 
dependency graph. Note that this operation is
+     * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
+     * artifact files.
+     *
+     * @param session the {@link Session}, must not be {@code null}
+     * @param root the Maven Dependency, must not be {@code null}
+     * @return the collection result, never {@code null}
+     * @throws DependencyResolverException if the dependency tree could not be 
built
+     * @throws IllegalArgumentException if an argument is null or invalid
+     * @see #collect(DependencyResolverRequest)
+     */
+    @Nonnull
+    default DependencyResolverResult collect(@Nonnull Session session, 
@Nonnull DependencyCoordinate root) {
+        return collect(DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.COLLECT, root));
+    }
 
     /**
-     * This method collects, flattens and resolves the dependencies.
+     * Collects the transitive dependencies of some artifacts and builds a 
dependency graph. Note that this operation is
+     * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
+     * artifact files.
      *
-     * @param request the request to resolve
-     * @return the result of the resolution
-     * @throws DependencyCollectorException
-     * @throws DependencyResolverException
-     * @throws ArtifactResolverException
+     * @param session the {@link Session}, must not be {@code null}
+     * @param project the {@link Project}, must not be {@code null}
+     * @return the collection result, never {@code null}
+     * @throws DependencyResolverException if the dependency tree could not be 
built
+     * @throws IllegalArgumentException if an argument is null or invalid
+     * @see #collect(DependencyResolverRequest)
+     */
+    @Nonnull
+    default DependencyResolverResult collect(@Nonnull Session session, 
@Nonnull Project project) {
+        return collect(
+                DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.COLLECT, project));
+    }
+
+    /**
+     * Collects the transitive dependencies of some artifacts and builds a 
dependency graph. Note that this operation is
+     * only concerned about determining the coordinates of the transitive 
dependencies and does not actually resolve the
+     * artifact files.
      *
-     * @see DependencyCollector#collect(DependencyCollectorRequest)
-     * @see #flatten(Session, Node, PathScope)
-     * @see ArtifactResolver#resolve(ArtifactResolverRequest)
+     * @param session the {@link Session}, must not be {@code null}
+     * @param artifact the {@link Artifact}, must not be {@code null}
+     * @return the collection result, never {@code null}
+     * @throws DependencyResolverException if the dependency tree could not be 
built
+     * @throws IllegalArgumentException if an argument is null or invalid
+     * @see #collect(DependencyResolverRequest)
      */
-    DependencyResolverResult resolve(DependencyResolverRequest request)
-            throws DependencyCollectorException, DependencyResolverException, 
ArtifactResolverException;
+    @Nonnull
+    default DependencyResolverResult collect(@Nonnull Session session, 
@Nonnull Artifact artifact) {
+        return collect(
+                DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.COLLECT, artifact));
+    }
+
+    /**
+     * Collects the transitive dependencies and builds a dependency graph.
+     * Note that this operation is only concerned about determining the 
coordinates of the
+     * transitive dependencies and does not actually resolve the artifact 
files.
+     *
+     * @param request the dependency collection request, must not be {@code 
null}
+     * @return the collection result, never {@code null}
+     * @throws DependencyResolverException if the dependency tree could not be 
built
+     * @throws IllegalArgumentException if an argument is null or invalid
+     *
+     * @see DependencyResolver#collect(Session, Project)
+     * @see DependencyResolver#collect(Session, DependencyCoordinate)
+     * @see DependencyResolver#collect(Session, Artifact)
+     */
+    @Nonnull
+    default DependencyResolverResult collect(@Nonnull 
DependencyResolverRequest request) {
+        if (request.getRequestType() != 
DependencyResolverRequest.RequestType.COLLECT) {
+            throw new IllegalArgumentException("requestType should be COLLECT 
when calling collect()");
+        }
+        return resolve(request);
+    }
+
+    /**
+     * Flattens a list of nodes.
+     *
+     * @param session
+     * @param node
+     * @param scope
+     * @return
+     * @throws DependencyResolverException
+     */
+    List<Node> flatten(Session session, Node node, PathScope scope) throws 
DependencyResolverException;
+
+    @Nonnull
+    default DependencyResolverResult flatten(@Nonnull Session session, 
@Nonnull Project project) {
+        return flatten(
+                DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.FLATTEN, project));
+    }
+
+    @Nonnull
+    default DependencyResolverResult flatten(
+            @Nonnull Session session, @Nonnull Project project, @Nonnull 
PathScope scope) {
+        return flatten(DependencyResolverRequest.build(
+                session, DependencyResolverRequest.RequestType.FLATTEN, 
project, scope));
+    }
+
+    @Nonnull
+    default DependencyResolverResult flatten(@Nonnull 
DependencyResolverRequest request) {
+        if (request.getRequestType() != 
DependencyResolverRequest.RequestType.FLATTEN) {
+            throw new IllegalArgumentException("requestType should be FLATTEN 
when calling flatten()");
+        }
+        return resolve(request);
+    }
 
     @Nonnull
     default DependencyResolverResult resolve(@Nonnull Session session, 
@Nonnull Project project) {
-        return resolve(DependencyResolverRequest.build(session, project));
+        return resolve(
+                DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.RESOLVE, project));
     }
 
     @Nonnull
     default DependencyResolverResult resolve(
             @Nonnull Session session, @Nonnull Project project, @Nonnull 
PathScope scope) {
-        return resolve(DependencyResolverRequest.build(session, project, 
scope));
+        return resolve(DependencyResolverRequest.build(
+                session, DependencyResolverRequest.RequestType.RESOLVE, 
project, scope));
     }
 
     @Nonnull
     default DependencyResolverResult resolve(@Nonnull Session session, 
@Nonnull DependencyCoordinate dependency) {
-        return resolve(DependencyResolverRequest.build(session, dependency));
+        return resolve(
+                DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.RESOLVE, dependency));
     }
 
     @Nonnull
     default DependencyResolverResult resolve(
             @Nonnull Session session, @Nonnull DependencyCoordinate 
dependency, @Nonnull PathScope scope) {
-        return resolve(DependencyResolverRequest.build(session, dependency, 
scope));
+        return resolve(DependencyResolverRequest.build(
+                session, DependencyResolverRequest.RequestType.RESOLVE, 
dependency, scope));
     }
 
     @Nonnull
     default DependencyResolverResult resolve(
             @Nonnull Session session, @Nonnull List<DependencyCoordinate> 
dependencies) {
-        return resolve(DependencyResolverRequest.build(session, dependencies));
+        return resolve(
+                DependencyResolverRequest.build(session, 
DependencyResolverRequest.RequestType.RESOLVE, dependencies));
     }
 
     @Nonnull
     default DependencyResolverResult resolve(
             @Nonnull Session session, @Nonnull List<DependencyCoordinate> 
dependencies, @Nonnull PathScope scope) {
-        return resolve(DependencyResolverRequest.build(session, dependencies, 
scope));
+        return resolve(DependencyResolverRequest.build(
+                session, DependencyResolverRequest.RequestType.RESOLVE, 
dependencies, scope));
     }
+
+    /**
+     * This method collects, flattens and resolves the dependencies.
+     *
+     * @param request the request to resolve
+     * @return the result of the resolution
+     * @throws DependencyResolverException
+     * @throws ArtifactResolverException
+     *
+     * @see DependencyResolver#collect(DependencyResolverRequest)
+     * @see #flatten(Session, Node, PathScope)
+     * @see ArtifactResolver#resolve(ArtifactResolverRequest)
+     */
+    DependencyResolverResult resolve(DependencyResolverRequest request)
+            throws DependencyResolverException, ArtifactResolverException;
 }
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
index 2f410a8a30..dfc7760fc7 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java
@@ -18,8 +18,11 @@
  */
 package org.apache.maven.api.services;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.function.Predicate;
 
 import org.apache.maven.api.Artifact;
@@ -30,14 +33,54 @@ import org.apache.maven.api.PathType;
 import org.apache.maven.api.Project;
 import org.apache.maven.api.Session;
 import org.apache.maven.api.annotations.Experimental;
+import org.apache.maven.api.annotations.Immutable;
 import org.apache.maven.api.annotations.Nonnull;
 import org.apache.maven.api.annotations.NotThreadSafe;
 import org.apache.maven.api.annotations.Nullable;
 
+/**
+ * A request to collect the transitive dependencies and to build a dependency 
graph from them. There are three ways to
+ * create a dependency graph. First, only the root dependency can be given. 
Second, a root dependency and direct
+ * dependencies can be specified in which case the specified direct 
dependencies are merged with the direct dependencies
+ * retrieved from the artifact descriptor of the root dependency. And last, 
only direct dependencies can be specified in
+ * which case the root node of the resulting graph has no associated 
dependency.
+ *
+ * @since 4.0.0
+ */
 @Experimental
-public interface DependencyResolverRequest extends DependencyCollectorRequest {
+@Immutable
+public interface DependencyResolverRequest {
+
+    enum RequestType {
+        COLLECT,
+        FLATTEN,
+        RESOLVE
+    }
+
+    @Nonnull
+    Session getSession();
+
+    @Nonnull
+    RequestType getRequestType();
+
+    @Nonnull
+    Optional<Project> getProject();
+
+    @Nonnull
+    Optional<Artifact> getRootArtifact();
+
+    @Nonnull
+    Optional<DependencyCoordinate> getRoot();
 
     @Nonnull
+    Collection<DependencyCoordinate> getDependencies();
+
+    @Nonnull
+    Collection<DependencyCoordinate> getManagedDependencies();
+
+    boolean getVerbose();
+
+    @Nullable
     PathScope getPathScope();
 
     /**
@@ -48,6 +91,7 @@ public interface DependencyResolverRequest extends 
DependencyCollectorRequest {
      *
      * @return a filter for the types of path (class-path, module-path, …) 
accepted by the tool
      */
+    @Nullable
     Predicate<PathType> getPathTypeFilter();
 
     @Nonnull
@@ -56,119 +100,202 @@ public interface DependencyResolverRequest extends 
DependencyCollectorRequest {
     }
 
     @Nonnull
-    static DependencyResolverRequest build(Session session, Project project) {
-        return build(session, project, PathScope.MAIN_RUNTIME);
+    static DependencyResolverRequest build(Session session, RequestType 
requestType, Artifact rootArtifact) {
+        return new DependencyResolverRequestBuilder()
+                .session(session)
+                .requestType(requestType)
+                .rootArtifact(rootArtifact)
+                .pathScope(PathScope.MAIN_RUNTIME)
+                .build();
     }
 
     @Nonnull
-    static DependencyResolverRequest build(Session session, Project project, 
PathScope scope) {
+    static DependencyResolverRequest build(Session session, RequestType 
requestType, Project project) {
+        return build(session, requestType, project, PathScope.MAIN_RUNTIME);
+    }
+
+    @Nonnull
+    static DependencyResolverRequest build(Session session, RequestType 
requestType, Project project, PathScope scope) {
         return new DependencyResolverRequestBuilder()
                 .session(session)
+                .requestType(requestType)
                 .project(project)
                 .pathScope(scope)
                 .build();
     }
 
     @Nonnull
-    static DependencyResolverRequest build(Session session, 
DependencyCoordinate dependency) {
-        return build(session, dependency, PathScope.MAIN_RUNTIME);
+    static DependencyResolverRequest build(Session session, RequestType 
requestType, DependencyCoordinate dependency) {
+        return build(session, requestType, dependency, PathScope.MAIN_RUNTIME);
     }
 
     @Nonnull
-    static DependencyResolverRequest build(Session session, 
DependencyCoordinate dependency, PathScope scope) {
+    static DependencyResolverRequest build(
+            Session session, RequestType requestType, DependencyCoordinate 
dependency, PathScope scope) {
         return new DependencyResolverRequestBuilder()
                 .session(session)
+                .requestType(requestType)
                 .dependency(dependency)
                 .pathScope(scope)
                 .build();
     }
 
     @Nonnull
-    static DependencyResolverRequest build(Session session, 
List<DependencyCoordinate> dependencies) {
-        return build(session, dependencies, PathScope.MAIN_RUNTIME);
+    static DependencyResolverRequest build(
+            Session session, RequestType requestType, 
List<DependencyCoordinate> dependencies) {
+        return build(session, requestType, dependencies, 
PathScope.MAIN_RUNTIME);
     }
 
     @Nonnull
-    static DependencyResolverRequest build(Session session, 
List<DependencyCoordinate> dependencies, PathScope scope) {
+    static DependencyResolverRequest build(
+            Session session, RequestType requestType, 
List<DependencyCoordinate> dependencies, PathScope scope) {
         return new DependencyResolverRequestBuilder()
                 .session(session)
+                .requestType(requestType)
                 .dependencies(dependencies)
                 .pathScope(scope)
                 .build();
     }
 
     @NotThreadSafe
-    class DependencyResolverRequestBuilder extends 
DependencyCollectorRequestBuilder {
+    class DependencyResolverRequestBuilder {
+
+        Session session;
+        RequestType requestType;
+        Project project;
+        Artifact rootArtifact;
+        DependencyCoordinate root;
+        List<DependencyCoordinate> dependencies = Collections.emptyList();
+        List<DependencyCoordinate> managedDependencies = 
Collections.emptyList();
+        boolean verbose;
         PathScope pathScope;
-
         Predicate<PathType> pathTypeFilter;
 
+        DependencyResolverRequestBuilder() {}
+
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder session(@Nonnull Session 
session) {
-            super.session(session);
+            this.session = session;
+            return this;
+        }
+
+        @Nonnull
+        public DependencyResolverRequestBuilder requestType(@Nonnull 
RequestType requestType) {
+            this.requestType = requestType;
             return this;
         }
 
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder project(@Nullable Project 
project) {
-            super.project(project);
+            this.project = project;
             return this;
         }
 
+        /**
+         * Sets the root artifact for the dependency graph.
+         * This must not be confused with {@link #root(DependencyCoordinate)}: 
The root <em>dependency</em>, like any
+         * other specified dependency, will be subject to dependency 
collection/resolution, i.e. should have an artifact
+         * descriptor and a corresponding artifact file. The root 
<em>artifact</em> on the other hand is only used
+         * as a label for the root node of the graph in case no root 
dependency was specified. As such, the configured
+         * root artifact is ignored if {@link #root(DependencyCoordinate)} has 
been set.
+         *
+         * @param rootArtifact the root artifact for the dependency graph, may 
be {@code null}
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder rootArtifact(@Nullable 
Artifact rootArtifact) {
-            super.rootArtifact(rootArtifact);
+            this.rootArtifact = rootArtifact;
             return this;
         }
 
+        /**
+         * @param root The root dependency
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
-        public DependencyResolverRequestBuilder root(@Nullable 
DependencyCoordinate root) {
-            super.root(root);
+        public DependencyResolverRequestBuilder root(@Nonnull 
DependencyCoordinate root) {
+            this.root = root;
             return this;
         }
 
+        /**
+         * Sets the direct dependencies. If both a root dependency and direct 
dependencies are given in the request, the
+         * direct dependencies from the request will be merged with the direct 
dependencies from the root dependency's
+         * artifact descriptor, giving higher priority to the dependencies 
from the request.
+         *
+         * @param dependencies the direct dependencies, may be {@code null}
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder dependencies(@Nullable 
List<DependencyCoordinate> dependencies) {
-            super.dependencies(dependencies);
+            this.dependencies = (dependencies != null) ? dependencies : 
Collections.emptyList();
             return this;
         }
 
+        /**
+         * Adds the specified direct dependency.
+         *
+         * @param dependency the dependency to add, may be {@code null}
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder dependency(@Nullable 
DependencyCoordinate dependency) {
-            super.dependency(dependency);
+            if (dependency != null) {
+                if (this.dependencies.isEmpty()) {
+                    this.dependencies = new ArrayList<>();
+                }
+                this.dependencies.add(dependency);
+            }
             return this;
         }
 
+        /**
+         * Sets the dependency management to apply to transitive dependencies. 
To clarify, this management does not
+         * apply to
+         * the direct dependencies of the root node.
+         *
+         * @param managedDependencies the dependency management, may be {@code 
null}
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder managedDependencies(
                 @Nullable List<DependencyCoordinate> managedDependencies) {
-            super.managedDependencies(managedDependencies);
+            this.managedDependencies = (managedDependencies != null) ? 
managedDependencies : Collections.emptyList();
             return this;
         }
 
+        /**
+         * Adds the specified managed dependency.
+         *
+         * @param managedDependency The managed dependency to add, may be 
{@code null} in which case the call
+         *                          will have no effect.
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder managedDependency(@Nullable 
DependencyCoordinate managedDependency) {
-            super.managedDependency(managedDependency);
+            if (managedDependency != null) {
+                if (this.managedDependencies.isEmpty()) {
+                    this.managedDependencies = new ArrayList<>();
+                }
+                this.managedDependencies.add(managedDependency);
+            }
             return this;
         }
 
+        /**
+         * Specifies that the collection should be verbose.
+         *
+         * @param verbose whether the collection should be verbose or not
+         * @return this request for chaining, never {@code null}
+         */
         @Nonnull
-        @Override
         public DependencyResolverRequestBuilder verbose(boolean verbose) {
-            super.verbose(verbose);
+            this.verbose = verbose;
             return this;
         }
 
         @Nonnull
-        public DependencyResolverRequestBuilder pathScope(@Nonnull PathScope 
pathScope) {
+        public DependencyResolverRequestBuilder pathScope(@Nullable PathScope 
pathScope) {
             this.pathScope = pathScope;
             return this;
         }
@@ -200,10 +327,11 @@ public interface DependencyResolverRequest extends 
DependencyCollectorRequest {
             return pathTypeFilter(desiredTypes::contains);
         }
 
-        @Override
+        @Nonnull
         public DependencyResolverRequest build() {
             return new DefaultDependencyResolverRequest(
                     session,
+                    requestType,
                     project,
                     rootArtifact,
                     root,
@@ -214,31 +342,92 @@ public interface DependencyResolverRequest extends 
DependencyCollectorRequest {
                     pathTypeFilter);
         }
 
-        static class DefaultDependencyResolverRequest extends 
DefaultDependencyCollectorRequest
-                implements DependencyResolverRequest {
+        static class DefaultDependencyResolverRequest extends BaseRequest 
implements DependencyResolverRequest {
+            private final RequestType requestType;
+            private final Project project;
+            private final Artifact rootArtifact;
+            private final DependencyCoordinate root;
+            private final Collection<DependencyCoordinate> dependencies;
+            private final Collection<DependencyCoordinate> managedDependencies;
+            private final boolean verbose;
             private final PathScope pathScope;
-
             private final Predicate<PathType> pathTypeFilter;
 
+            /**
+             * Creates a request with the specified properties.
+             *
+             * @param session      {@link Session}
+             * @param rootArtifact The root dependency whose transitive 
dependencies should be collected, may be {@code
+             *                     null}.
+             */
             DefaultDependencyResolverRequest(
-                    Session session,
-                    Project project,
-                    Artifact rootArtifact,
-                    DependencyCoordinate root,
-                    Collection<DependencyCoordinate> dependencies,
-                    Collection<DependencyCoordinate> managedDependencies,
+                    @Nonnull Session session,
+                    @Nonnull RequestType requestType,
+                    @Nullable Project project,
+                    @Nullable Artifact rootArtifact,
+                    @Nullable DependencyCoordinate root,
+                    @Nonnull Collection<DependencyCoordinate> dependencies,
+                    @Nonnull Collection<DependencyCoordinate> 
managedDependencies,
                     boolean verbose,
-                    PathScope pathScope,
-                    Predicate<PathType> pathTypeFilter) {
-                super(session, project, rootArtifact, root, dependencies, 
managedDependencies, verbose);
-                this.pathScope = nonNull(pathScope, "pathScope cannot be 
null");
+                    @Nullable PathScope pathScope,
+                    @Nullable Predicate<PathType> pathTypeFilter) {
+                super(session);
+                this.requestType = nonNull(requestType, "requestType cannot be 
null");
+                this.project = project;
+                this.rootArtifact = rootArtifact;
+                this.root = root;
+                this.dependencies = unmodifiable(nonNull(dependencies, 
"dependencies cannot be null"));
+                this.managedDependencies =
+                        unmodifiable(nonNull(managedDependencies, 
"managedDependencies cannot be null"));
+                this.verbose = verbose;
+                this.pathScope = pathScope;
                 this.pathTypeFilter = (pathTypeFilter != null) ? 
pathTypeFilter : (t) -> true;
-                if (verbose) {
-                    throw new IllegalArgumentException("verbose cannot be true 
for resolving dependencies");
+                if (verbose && requestType != RequestType.COLLECT) {
+                    throw new IllegalArgumentException("verbose cannot only be 
true when collecting dependencies");
                 }
             }
 
             @Nonnull
+            @Override
+            public RequestType getRequestType() {
+                return requestType;
+            }
+
+            @Nonnull
+            @Override
+            public Optional<Project> getProject() {
+                return Optional.ofNullable(project);
+            }
+
+            @Nonnull
+            @Override
+            public Optional<Artifact> getRootArtifact() {
+                return Optional.ofNullable(rootArtifact);
+            }
+
+            @Nonnull
+            @Override
+            public Optional<DependencyCoordinate> getRoot() {
+                return Optional.ofNullable(root);
+            }
+
+            @Nonnull
+            @Override
+            public Collection<DependencyCoordinate> getDependencies() {
+                return dependencies;
+            }
+
+            @Nonnull
+            @Override
+            public Collection<DependencyCoordinate> getManagedDependencies() {
+                return managedDependencies;
+            }
+
+            @Override
+            public boolean getVerbose() {
+                return verbose;
+            }
+
             @Override
             public PathScope getPathScope() {
                 return pathScope;
@@ -248,6 +437,12 @@ public interface DependencyResolverRequest extends 
DependencyCollectorRequest {
             public Predicate<PathType> getPathTypeFilter() {
                 return pathTypeFilter;
             }
+
+            @Nonnull
+            @Override
+            public String toString() {
+                return getRoot() + " -> " + getDependencies();
+            }
         }
     }
 }
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
index 9579ad6d17..e7ab86d011 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java
@@ -29,9 +29,32 @@ import org.apache.maven.api.Node;
 import org.apache.maven.api.PathType;
 import org.apache.maven.api.annotations.Experimental;
 import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.annotations.Nullable;
 
+/**
+ * The result of a dependency resolution request.
+ *
+ * @since 4.0.0
+ * @see DependencyResolver#resolve(DependencyResolverRequest)
+ */
 @Experimental
-public interface DependencyResolverResult extends DependencyCollectorResult {
+public interface DependencyResolverResult {
+
+    /**
+     * Gets the exceptions that occurred while building the dependency graph.
+     *
+     * @return the exceptions that occurred, never {@code null}
+     */
+    @Nonnull
+    List<Exception> getExceptions();
+
+    /**
+     * Gets the root node of the dependency graph.
+     *
+     * @return the root node of the dependency graph or {@code null} if none
+     */
+    @Nullable
+    Node getRoot();
 
     /**
      * The ordered list of the flattened dependency nodes.
diff --git 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
index 348be6135b..2247aa7b2e 100644
--- 
a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
+++ 
b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java
@@ -75,5 +75,5 @@ public interface ProjectBuilderResult {
      * @return the result of the dependency resolution for the project
      */
     @Nonnull
-    Optional<DependencyCollectorResult> getDependencyResolverResult();
+    Optional<DependencyResolverResult> getDependencyResolverResult();
 }
diff --git 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/AbstractSession.java
 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/AbstractSession.java
index 464941d23c..d8a3a10f57 100644
--- 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/AbstractSession.java
+++ 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/AbstractSession.java
@@ -596,39 +596,41 @@ public abstract class AbstractSession implements 
InternalSession {
     }
 
     /**
-     * Shortcut for 
<code>getService(DependencyCollector.class).collect(...)</code>
+     * Shortcut for 
<code>getService(DependencyResolver.class).collect(...)</code>
      *
-     * @throws DependencyCollectorException if the dependency collection failed
-     * @see DependencyCollector#collect(Session, Artifact)
+     * @throws DependencyResolverException if the dependency collection failed
+     * @see DependencyResolver#collect(Session, Artifact)
      */
     @Nonnull
     @Override
     public Node collectDependencies(@Nonnull Artifact artifact) {
-        return getService(DependencyCollector.class).collect(this, 
artifact).getRoot();
+        return getService(DependencyResolver.class).collect(this, 
artifact).getRoot();
     }
 
     /**
-     * Shortcut for 
<code>getService(DependencyCollector.class).collect(...)</code>
+     * Shortcut for 
<code>getService(DependencyResolver.class).collect(...)</code>
      *
-     * @throws DependencyCollectorException if the dependency collection failed
-     * @see DependencyCollector#collect(Session, Project)
+     * @throws DependencyResolverException if the dependency collection failed
+     * @see DependencyResolver#collect(Session, Project)
      */
     @Nonnull
     @Override
     public Node collectDependencies(@Nonnull Project project) {
-        return getService(DependencyCollector.class).collect(this, 
project).getRoot();
+        return getService(DependencyResolver.class).collect(this, 
project).getRoot();
     }
 
     /**
-     * Shortcut for 
<code>getService(DependencyCollector.class).collect(...)</code>
+     * Shortcut for 
<code>getService(DependencyResolver.class).collect(...)</code>
      *
-     * @throws DependencyCollectorException if the dependency collection failed
-     * @see DependencyCollector#collect(Session, DependencyCoordinate)
+     * @throws DependencyResolverException if the dependency collection failed
+     * @see DependencyResolver#collect(Session, DependencyCoordinate)
      */
     @Nonnull
     @Override
     public Node collectDependencies(@Nonnull DependencyCoordinate dependency) {
-        return getService(DependencyCollector.class).collect(this, 
dependency).getRoot();
+        Node root =
+                getService(DependencyResolver.class).collect(this, 
dependency).getRoot();
+        return root.getChildren().iterator().next();
     }
 
     @Nonnull
@@ -662,6 +664,7 @@ public abstract class AbstractSession implements 
InternalSession {
         return getService(DependencyResolver.class)
                 .resolve(DependencyResolverRequest.builder()
                         .session(this)
+                        
.requestType(DependencyResolverRequest.RequestType.RESOLVE)
                         .dependency(dependency)
                         .pathScope(scope)
                         .pathTypeFilter(desiredTypes)
@@ -675,6 +678,7 @@ public abstract class AbstractSession implements 
InternalSession {
         return getService(DependencyResolver.class)
                 .resolve(DependencyResolverRequest.builder()
                         .session(this)
+                        
.requestType(DependencyResolverRequest.RequestType.RESOLVE)
                         .project(project)
                         .pathScope(scope)
                         .pathTypeFilter(desiredTypes)
diff --git 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java
 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java
deleted file mode 100644
index bd63ca1280..0000000000
--- 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.maven.internal.impl;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.maven.api.Artifact;
-import org.apache.maven.api.DependencyCoordinate;
-import org.apache.maven.api.Node;
-import org.apache.maven.api.Project;
-import org.apache.maven.api.RemoteRepository;
-import org.apache.maven.api.annotations.Nonnull;
-import org.apache.maven.api.di.Named;
-import org.apache.maven.api.di.Singleton;
-import org.apache.maven.api.services.DependencyCollector;
-import org.apache.maven.api.services.DependencyCollectorException;
-import org.apache.maven.api.services.DependencyCollectorRequest;
-import org.apache.maven.api.services.DependencyCollectorResult;
-import org.apache.maven.api.services.ProjectManager;
-import org.eclipse.aether.DefaultRepositorySystemSession;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.collection.CollectRequest;
-import org.eclipse.aether.collection.CollectResult;
-import org.eclipse.aether.collection.DependencyCollectionException;
-import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver;
-
-import static org.apache.maven.internal.impl.Utils.nonNull;
-
-@Named
-@Singleton
-public class DefaultDependencyCollector implements DependencyCollector {
-
-    @Nonnull
-    @Override
-    public DependencyCollectorResult collect(@Nonnull 
DependencyCollectorRequest request)
-            throws DependencyCollectorException, IllegalArgumentException {
-        nonNull(request, "request");
-        InternalSession session = InternalSession.from(request.getSession());
-
-        Artifact rootArtifact;
-        DependencyCoordinate root;
-        Collection<DependencyCoordinate> dependencies;
-        Collection<DependencyCoordinate> managedDependencies;
-        List<RemoteRepository> remoteRepositories;
-        if (request.getProject().isPresent()) {
-            Project project = request.getProject().get();
-            rootArtifact = project.getPomArtifact();
-            root = null;
-            dependencies = project.getDependencies();
-            managedDependencies = project.getManagedDependencies();
-            remoteRepositories = 
session.getService(ProjectManager.class).getRemoteProjectRepositories(project);
-        } else {
-            rootArtifact = request.getRootArtifact().orElse(null);
-            root = request.getRoot().orElse(null);
-            dependencies = request.getDependencies();
-            managedDependencies = request.getManagedDependencies();
-            remoteRepositories = session.getRemoteRepositories();
-        }
-        CollectRequest collectRequest = new CollectRequest()
-                .setRootArtifact(rootArtifact != null ? 
session.toArtifact(rootArtifact) : null)
-                .setRoot(root != null ? session.toDependency(root, false) : 
null)
-                .setDependencies(session.toDependencies(dependencies, false))
-                
.setManagedDependencies(session.toDependencies(managedDependencies, true))
-                .setRepositories(session.toRepositories(remoteRepositories));
-
-        RepositorySystemSession systemSession = session.getSession();
-        if (request.getVerbose()) {
-            systemSession = new DefaultRepositorySystemSession(systemSession)
-                    .setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, 
true)
-                    
.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true);
-        }
-
-        try {
-            final CollectResult result =
-                    
session.getRepositorySystem().collectDependencies(systemSession, 
collectRequest);
-            return new DependencyCollectorResult() {
-                @Override
-                public List<Exception> getExceptions() {
-                    return result.getExceptions();
-                }
-
-                @Override
-                public Node getRoot() {
-                    return session.getNode(result.getRoot(), 
request.getVerbose());
-                }
-            };
-        } catch (DependencyCollectionException e) {
-            throw new DependencyCollectorException("Unable to collect 
dependencies", e);
-        }
-    }
-}
diff --git 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java
 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java
new file mode 100644
index 0000000000..1105c2ab5d
--- /dev/null
+++ 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.maven.internal.impl;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.apache.maven.api.*;
+import org.apache.maven.api.Artifact;
+import org.apache.maven.api.ArtifactCoordinate;
+import org.apache.maven.api.Dependency;
+import org.apache.maven.api.Node;
+import org.apache.maven.api.PathType;
+import org.apache.maven.api.Session;
+import org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.di.Named;
+import org.apache.maven.api.di.Singleton;
+import org.apache.maven.api.services.*;
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.RepositorySystemSession;
+import org.eclipse.aether.collection.CollectRequest;
+import org.eclipse.aether.collection.CollectResult;
+import org.eclipse.aether.collection.DependencyCollectionException;
+import org.eclipse.aether.graph.DependencyFilter;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
+import org.eclipse.aether.util.graph.transformer.ConflictResolver;
+
+import static org.apache.maven.internal.impl.Utils.cast;
+import static org.apache.maven.internal.impl.Utils.map;
+import static org.apache.maven.internal.impl.Utils.nonNull;
+
+@Named
+@Singleton
+public class DefaultDependencyResolver implements DependencyResolver {
+
+    @Nonnull
+    @Override
+    public DependencyResolverResult collect(@Nonnull DependencyResolverRequest 
request)
+            throws DependencyResolverException, IllegalArgumentException {
+        nonNull(request, "request");
+        InternalSession session = InternalSession.from(request.getSession());
+
+        Artifact rootArtifact;
+        DependencyCoordinate root;
+        Collection<DependencyCoordinate> dependencies;
+        Collection<DependencyCoordinate> managedDependencies;
+        List<RemoteRepository> remoteRepositories;
+        if (request.getProject().isPresent()) {
+            Project project = request.getProject().get();
+            rootArtifact = project.getPomArtifact();
+            root = null;
+            dependencies = project.getDependencies();
+            managedDependencies = project.getManagedDependencies();
+            remoteRepositories = 
session.getService(ProjectManager.class).getRemoteProjectRepositories(project);
+        } else {
+            rootArtifact = request.getRootArtifact().orElse(null);
+            root = request.getRoot().orElse(null);
+            dependencies = request.getDependencies();
+            managedDependencies = request.getManagedDependencies();
+            remoteRepositories = session.getRemoteRepositories();
+        }
+        CollectRequest collectRequest = new CollectRequest()
+                .setRootArtifact(rootArtifact != null ? 
session.toArtifact(rootArtifact) : null)
+                .setRoot(root != null ? session.toDependency(root, false) : 
null)
+                .setDependencies(session.toDependencies(dependencies, false))
+                
.setManagedDependencies(session.toDependencies(managedDependencies, true))
+                .setRepositories(session.toRepositories(remoteRepositories));
+
+        RepositorySystemSession systemSession = session.getSession();
+        if (request.getVerbose()) {
+            systemSession = new DefaultRepositorySystemSession(systemSession)
+                    .setConfigProperty(ConflictResolver.CONFIG_PROP_VERBOSE, 
true)
+                    
.setConfigProperty(DependencyManagerUtils.CONFIG_PROP_VERBOSE, true);
+        }
+
+        try {
+            final CollectResult result =
+                    
session.getRepositorySystem().collectDependencies(systemSession, 
collectRequest);
+            return new DefaultDependencyResolverResult(
+                    null, result.getExceptions(), 
session.getNode(result.getRoot(), request.getVerbose()), 0);
+        } catch (DependencyCollectionException e) {
+            throw new DependencyResolverException("Unable to collect 
dependencies", e);
+        }
+    }
+
+    @Override
+    public List<Node> flatten(Session s, Node node, PathScope scope) throws 
DependencyResolverException {
+        InternalSession session = InternalSession.from(s);
+        DependencyNode root = cast(AbstractNode.class, node, 
"node").getDependencyNode();
+        List<DependencyNode> dependencies = session.getRepositorySystem()
+                .flattenDependencyNodes(session.getSession(), root, 
getScopeDependencyFilter(scope));
+        dependencies.remove(root);
+        return map(dependencies, session::getNode);
+    }
+
+    private static DependencyFilter getScopeDependencyFilter(PathScope scope) {
+        Set<String> scopes =
+                
scope.dependencyScopes().stream().map(DependencyScope::id).collect(Collectors.toSet());
+        return (n, p) -> {
+            org.eclipse.aether.graph.Dependency d = n.getDependency();
+            return d == null || scopes.contains(d.getScope());
+        };
+    }
+
+    /**
+     * Collects, flattens and resolves the dependencies.
+     *
+     * @param request the request to resolve
+     * @return the result of the resolution
+     */
+    @Override
+    public DependencyResolverResult resolve(DependencyResolverRequest request)
+            throws DependencyResolverException, DependencyResolverException, 
ArtifactResolverException {
+        InternalSession session =
+                InternalSession.from(nonNull(request, "request").getSession());
+        DependencyResolverResult result;
+        DependencyResolverResult collectorResult = collect(request);
+        if (request.getRequestType() == 
DependencyResolverRequest.RequestType.COLLECT) {
+            result = collectorResult;
+        } else {
+            List<Node> nodes = flatten(session, collectorResult.getRoot(), 
request.getPathScope());
+            List<ArtifactCoordinate> coordinates = nodes.stream()
+                    .map(Node::getDependency)
+                    .filter(Objects::nonNull)
+                    .map(Artifact::toCoordinate)
+                    .collect(Collectors.toList());
+            Predicate<PathType> filter = request.getPathTypeFilter();
+            if (request.getRequestType() == 
DependencyResolverRequest.RequestType.FLATTEN) {
+                DefaultDependencyResolverResult flattenResult = new 
DefaultDependencyResolverResult(
+                        null, collectorResult.getExceptions(), 
collectorResult.getRoot(), nodes.size());
+                for (Node node : nodes) {
+                    flattenResult.addNode(node);
+                }
+                result = flattenResult;
+            } else {
+                PathModularizationCache cache = new PathModularizationCache(); 
// TODO: should be project-wide cache.
+                DefaultDependencyResolverResult resolverResult = new 
DefaultDependencyResolverResult(
+                        cache, collectorResult.getExceptions(), 
collectorResult.getRoot(), nodes.size());
+                Map<Artifact, Path> artifacts = 
session.resolveArtifacts(coordinates);
+                for (Node node : nodes) {
+                    Dependency d = node.getDependency();
+                    Path path = (d != null) ? artifacts.get(d) : null;
+                    try {
+                        resolverResult.addDependency(node, d, filter, path);
+                    } catch (IOException e) {
+                        throw cannotReadModuleInfo(path, e);
+                    }
+                }
+                result = resolverResult;
+            }
+        }
+        return result;
+    }
+
+    private static DependencyResolverException cannotReadModuleInfo(final Path 
path, final IOException cause) {
+        return new DependencyResolverException("Cannot read module information 
of " + path, cause);
+    }
+}
diff --git 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolverResult.java
 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolverResult.java
index baf7b44424..ffad2adab5 100644
--- 
a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolverResult.java
+++ 
b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolverResult.java
@@ -94,7 +94,7 @@ class DefaultDependencyResolverResult implements 
DependencyResolverResult {
 
     /**
      * Creates an initially empty result. Callers should add path elements by 
calls
-     * to {@link #addDependency(Node, Dependency, Predicate, Path, 
PathModularizationCache)}.
+     * to {@link #addDependency(Node, Dependency, Predicate, Path)}.
      *
      * @param cache cache of module information about each dependency
      * @param exceptions the exceptions that occurred while building the 
dependency graph
@@ -201,6 +201,15 @@ class DefaultDependencyResolverResult implements 
DependencyResolverResult {
         }
     }
 
+    /**
+     * Adds a dependency node to the result.
+     *
+     * @param node the dependency node
+     */
+    void addNode(Node node) {
+        nodes.add(node);
+    }
+
     /**
      * Adds a dependency to the result. This method populates the {@link 
#nodes}, {@link #paths},
      * {@link #dispatchedPaths} and {@link #dependencies} collections with the 
given arguments.
diff --git 
a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java
 
b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java
index b6e2bbc815..750aa9c084 100644
--- 
a/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java
+++ 
b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/standalone/ApiRunner.java
@@ -85,7 +85,7 @@ public class ApiRunner {
         injector.bindImplicit(DefaultArtifactInstaller.class);
         injector.bindImplicit(DefaultArtifactResolver.class);
         injector.bindImplicit(DefaultChecksumAlgorithmService.class);
-        injector.bindImplicit(DefaultDependencyCollector.class);
+        injector.bindImplicit(DefaultDependencyResolver.class);
         injector.bindImplicit(DefaultDependencyCoordinateFactory.class);
         injector.bindImplicit(DefaultLocalRepositoryManager.class);
         injector.bindImplicit(DefaultMessageBuilderFactory.class);
diff --git 
a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java
 
b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java
deleted file mode 100644
index 254ee13f06..0000000000
--- 
a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you 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 org.apache.maven.internal.impl;
-
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-import org.apache.maven.api.*;
-import org.apache.maven.api.Artifact;
-import org.apache.maven.api.ArtifactCoordinate;
-import org.apache.maven.api.Dependency;
-import org.apache.maven.api.Node;
-import org.apache.maven.api.PathType;
-import org.apache.maven.api.Session;
-import org.apache.maven.api.services.*;
-import org.eclipse.aether.graph.DependencyFilter;
-import org.eclipse.aether.graph.DependencyNode;
-
-import static org.apache.maven.internal.impl.Utils.cast;
-import static org.apache.maven.internal.impl.Utils.map;
-import static org.apache.maven.internal.impl.Utils.nonNull;
-
-@Named
-@Singleton
-public class DefaultDependencyResolver implements DependencyResolver {
-
-    @Override
-    public List<Node> flatten(Session s, Node node, PathScope scope) throws 
DependencyResolverException {
-        InternalSession session = InternalSession.from(s);
-        DependencyNode root = cast(AbstractNode.class, node, 
"node").getDependencyNode();
-        List<DependencyNode> dependencies = session.getRepositorySystem()
-                .flattenDependencyNodes(session.getSession(), root, 
getScopeDependencyFilter(scope));
-        dependencies.remove(root);
-        return map(dependencies, session::getNode);
-    }
-
-    private static DependencyFilter getScopeDependencyFilter(PathScope scope) {
-        Set<String> scopes =
-                
scope.dependencyScopes().stream().map(DependencyScope::id).collect(Collectors.toSet());
-        return (n, p) -> {
-            org.eclipse.aether.graph.Dependency d = n.getDependency();
-            return d == null || scopes.contains(d.getScope());
-        };
-    }
-
-    /**
-     * Collects, flattens and resolves the dependencies.
-     *
-     * @param request the request to resolve
-     * @return the result of the resolution
-     */
-    @Override
-    public DependencyResolverResult resolve(DependencyResolverRequest request)
-            throws DependencyCollectorException, DependencyResolverException, 
ArtifactResolverException {
-        InternalSession session =
-                InternalSession.from(nonNull(request, "request").getSession());
-        Predicate<PathType> filter = request.getPathTypeFilter();
-        PathModularizationCache cache = new PathModularizationCache(); // 
TODO: should be project-wide cache.
-        DependencyCollectorResult collectorResult =
-                session.getService(DependencyCollector.class).collect(request);
-        List<Node> nodes = flatten(session, collectorResult.getRoot(), 
request.getPathScope());
-        List<ArtifactCoordinate> coordinates = nodes.stream()
-                .map(Node::getDependency)
-                .filter(Objects::nonNull)
-                .map(Artifact::toCoordinate)
-                .collect(Collectors.toList());
-        Map<Artifact, Path> artifacts = session.resolveArtifacts(coordinates);
-        DefaultDependencyResolverResult result = new 
DefaultDependencyResolverResult(
-                cache, collectorResult.getExceptions(), 
collectorResult.getRoot(), nodes.size());
-        for (Node node : nodes) {
-            Dependency d = node.getDependency();
-            Path path = (d != null) ? artifacts.get(d) : null;
-            try {
-                result.addDependency(node, d, filter, path);
-            } catch (IOException e) {
-                throw cannotReadModuleInfo(path, e);
-            }
-        }
-        return result;
-    }
-
-    private static DependencyResolverException cannotReadModuleInfo(final Path 
path, final IOException cause) {
-        return new DependencyResolverException("Cannot read module information 
of " + path, cause);
-    }
-}
diff --git 
a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java
 
b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java
index d785dad9f8..cbc2e0afd7 100644
--- 
a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java
+++ 
b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java
@@ -31,11 +31,10 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 
-import org.apache.maven.api.Node;
 import org.apache.maven.api.Project;
 import org.apache.maven.api.annotations.Nonnull;
 import org.apache.maven.api.services.BuilderProblem;
-import org.apache.maven.api.services.DependencyCollectorResult;
+import org.apache.maven.api.services.DependencyResolverResult;
 import org.apache.maven.api.services.ProjectBuilder;
 import org.apache.maven.api.services.ProjectBuilderException;
 import org.apache.maven.api.services.ProjectBuilderRequest;
@@ -170,19 +169,10 @@ public class DefaultProjectBuilder implements 
ProjectBuilder {
 
                 @Nonnull
                 @Override
-                public Optional<DependencyCollectorResult> 
getDependencyResolverResult() {
+                public Optional<DependencyResolverResult> 
getDependencyResolverResult() {
                     return 
Optional.ofNullable(res.getDependencyResolutionResult())
-                            .map(r -> new DependencyCollectorResult() {
-                                @Override
-                                public List<Exception> getExceptions() {
-                                    return r.getCollectionErrors();
-                                }
-
-                                @Override
-                                public Node getRoot() {
-                                    return 
session.getNode(r.getDependencyGraph());
-                                }
-                            });
+                            .map(r -> new DefaultDependencyResolverResult(
+                                    null, r.getCollectionErrors(), 
session.getNode(r.getDependencyGraph()), 0));
                 }
             };
         } catch (ProjectBuildingException e) {
diff --git 
a/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject 
b/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
index 285f768d41..dbbc28f99d 100644
--- 
a/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
+++ 
b/maven-core/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject
@@ -11,8 +11,8 @@ org.apache.maven.internal.impl.DefaultArtifactFactory
 org.apache.maven.internal.impl.DefaultArtifactInstaller
 org.apache.maven.internal.impl.DefaultArtifactResolver
 org.apache.maven.internal.impl.DefaultChecksumAlgorithmService
-org.apache.maven.internal.impl.DefaultDependencyCollector
 org.apache.maven.internal.impl.DefaultDependencyCoordinateFactory
+org.apache.maven.internal.impl.DefaultDependencyResolver
 org.apache.maven.internal.impl.DefaultLocalRepositoryManager
 org.apache.maven.internal.impl.DefaultMessageBuilderFactory
 org.apache.maven.internal.impl.DefaultModelUrlNormalizer

Reply via email to