You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2021/12/18 18:41:28 UTC

[maven-dependency-tree] branch MSHARED-1005 created (now accf4b9)

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

slachiewicz pushed a change to branch MSHARED-1005
in repository https://gitbox.apache.org/repos/asf/maven-dependency-tree.git.


      at accf4b9  [MSHARED-1004] Require Maven 3.2.5+

This branch includes the following new commits:

     new accf4b9  [MSHARED-1004] Require Maven 3.2.5+

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[maven-dependency-tree] 01/01: [MSHARED-1004] Require Maven 3.2.5+

Posted by sl...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

slachiewicz pushed a commit to branch MSHARED-1005
in repository https://gitbox.apache.org/repos/asf/maven-dependency-tree.git

commit accf4b95b4065162829745a52d936e5390ed5a3e
Author: Sylwester Lachiewicz <sl...@apache.org>
AuthorDate: Sat Dec 18 19:41:21 2021 +0100

    [MSHARED-1004] Require Maven 3.2.5+
---
 pom.xml                                            |    8 +-
 .../graph/DependencyCollectorBuilder.java          |    2 +-
 .../dependency/graph/DependencyGraphBuilder.java   |    2 +-
 .../DefaultDependencyCollectorBuilder.java         |   26 +-
 .../internal/DefaultDependencyGraphBuilder.java    |   28 +-
 .../shared/dependency/graph/internal/Invoker.java  |   97 --
 .../Maven31DependencyCollectorBuilder.java         |   80 +-
 .../internal/Maven31DependencyGraphBuilder.java    |   53 +-
 .../internal/Maven3DependencyCollectorBuilder.java |  321 -----
 .../internal/Maven3DependencyGraphBuilder.java     |  155 ---
 .../graph/internal/maven30/ConflictIdSorter.java   |  370 ------
 .../graph/internal/maven30/ConflictResolver.java   | 1314 --------------------
 .../maven30/ExclusionDependencySelector.java       |  228 ----
 .../graph/internal/maven30/JavaScopeDeriver.java   |   72 --
 .../graph/internal/maven30/JavaScopeSelector.java  |  102 --
 .../Maven3DirectScopeDependencySelector.java       |  132 --
 .../internal/maven30/NearestVersionSelector.java   |  176 ---
 .../maven30/SimpleOptionalitySelector.java         |   64 -
 .../internal/maven30/VerboseJavaScopeSelector.java |   64 -
 19 files changed, 64 insertions(+), 3230 deletions(-)

diff --git a/pom.xml b/pom.xml
index 08fc42f..25c3ed1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,7 +69,7 @@
     <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-core</artifactId>
-      <version>3.0.5</version>
+      <version>3.2.5</version>
     </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
@@ -77,12 +77,6 @@
       <optional>true</optional>
     </dependency>
     <dependency>
-      <groupId>org.sonatype.aether</groupId>
-      <artifactId>aether-api</artifactId>
-      <version>1.13.1</version>
-      <optional>true</optional>
-    </dependency>
-    <dependency>
       <groupId>org.eclipse.aether</groupId>
       <artifactId>aether-api</artifactId>
       <version>1.1.0</version>
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/DependencyCollectorBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/DependencyCollectorBuilder.java
index 9ece96f..38e60e5 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/DependencyCollectorBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/DependencyCollectorBuilder.java
@@ -23,7 +23,7 @@ import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.project.ProjectBuildingRequest;
 
 /**
- * Maven project dependency raw dependency collector API, providing an abstraction layer against Maven 3 and Maven 3.1+
+ * Maven project dependency raw dependency collector API, providing an abstraction layer against Maven 3.1+
  * particular Aether implementations.
  * 
  * @author Gabriel Belingueres
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java
index cab4ce8..3c9c37e 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/DependencyGraphBuilder.java
@@ -26,7 +26,7 @@ import org.apache.maven.project.ProjectBuildingRequest;
 import java.util.Collection;
 
 /**
- * Maven project dependency graph builder API, neutral against Maven 2 or Maven 3.
+ * Maven project dependency graph builder API, neutral Maven 3.
  *
  * @author Hervé Boutemy
  * @since 2.0
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyCollectorBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyCollectorBuilder.java
index cddf101..4f9db16 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyCollectorBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyCollectorBuilder.java
@@ -20,7 +20,6 @@ package org.apache.maven.shared.dependency.graph.internal;
  */
 
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.execution.MavenSession;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
 import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder;
@@ -36,7 +35,7 @@ import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 
 /**
- * Default project dependency raw dependency collector API, providing an abstraction layer against Maven 3 and Maven
+ * Default project dependency raw dependency collector API, providing an abstraction layer against Maven
  * 3.1+ particular Aether implementations.
  * 
  * @author Gabriel Belingueres
@@ -55,17 +54,15 @@ public class DefaultDependencyCollectorBuilder
     {
         try
         {
-            String hint = isMaven31() ? "maven31" : "maven3";
 
             DependencyCollectorBuilder effectiveGraphBuilder =
-                (DependencyCollectorBuilder) container.lookup( DependencyCollectorBuilder.class.getCanonicalName(),
-                                                               hint );
+                    container.lookup( DependencyCollectorBuilder.class, "maven31" );
 
             if ( getLogger().isDebugEnabled() )
             {
                 MavenProject project = buildingRequest.getProject();
 
-                getLogger().debug( "building " + hint + " RAW dependency tree for " + project.getId() + " with "
+                getLogger().debug( "building Maven 3.1+ RAW dependency tree for " + project.getId() + " with "
                     + effectiveGraphBuilder.getClass().getSimpleName() );
             }
 
@@ -78,23 +75,6 @@ public class DefaultDependencyCollectorBuilder
     }
 
     /**
-     * @return true if the current Maven version is Maven 3.1.
-     */
-    protected static boolean isMaven31()
-    {
-        try
-        {
-            Class<?> repoSessionClass =  MavenSession.class.getMethod( "getRepositorySession" ).getReturnType();
-            
-            return "org.eclipse.aether.RepositorySystemSession".equals( repoSessionClass.getName() );
-        }
-        catch ( NoSuchMethodException e )
-        {
-            throw new IllegalStateException( "Cannot determine return type of MavenSession.getRepositorySession" );
-        }
-    }
-
-    /**
      * Injects the Plexus content.
      *
      * @param context Plexus context to inject.
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java
index 84f27f3..d183ba2 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/DefaultDependencyGraphBuilder.java
@@ -20,7 +20,6 @@ package org.apache.maven.shared.dependency.graph.internal;
  */
 
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.execution.MavenSession;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.ProjectBuildingRequest;
 import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
@@ -36,10 +35,8 @@ import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
 
 /**
- * Default dependency graph builder that detects current Maven version to delegate to either Maven 3.0 or 3.1+ specific
- * code.
+ * Default dependency graph builder that detects current Maven version and delegate to 3.1+ specific code.
  *
- * @see Maven3DependencyGraphBuilder
  * @see Maven31DependencyGraphBuilder
  * @author Hervé Boutemy
  * @since 2.0
@@ -65,16 +62,14 @@ public class DefaultDependencyGraphBuilder
     {
         try
         {
-            String hint = isMaven31() ? "maven31" : "maven3";
-
             DependencyGraphBuilder effectiveGraphBuilder =
-                (DependencyGraphBuilder) container.lookup( DependencyGraphBuilder.class.getCanonicalName(), hint );
+                    container.lookup( DependencyGraphBuilder.class, "maven31" );
             
             if ( getLogger().isDebugEnabled() )
             {
                 MavenProject project = buildingRequest.getProject();
                 
-                getLogger().debug( "building " + hint + " dependency graph for " + project.getId() + " with "
+                getLogger().debug( "building Maven 3.1+ dependency graph for " + project.getId() + " with "
                                 + effectiveGraphBuilder.getClass().getSimpleName() );
             }
 
@@ -87,23 +82,6 @@ public class DefaultDependencyGraphBuilder
     }
 
     /**
-     * @return true if the current Maven version is Maven 3.1.
-     */
-    protected static boolean isMaven31()
-    {
-        try
-        {
-            Class<?> repoSessionClass =  MavenSession.class.getMethod( "getRepositorySession" ).getReturnType();
-            
-            return "org.eclipse.aether.RepositorySystemSession".equals( repoSessionClass.getName() );
-        }
-        catch ( NoSuchMethodException e )
-        {
-            throw new IllegalStateException( "Cannot determine return type of MavenSession.getRepositorySession" );
-        }
-    }
-
-    /**
      * Injects the Plexus content.
      *
      * @param context   Plexus context to inject.
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Invoker.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Invoker.java
deleted file mode 100644
index 8cc8851..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Invoker.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal;
-
-/*
- * 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.
- */
-
-import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
-
-/**
- * Invokes method on objects using reflection.
- */
-final class Invoker
-{
-    private Invoker()
-    {
-        // do not instantiate
-    }
-
-    static <T extends Exception> Object invoke( Object object, String method, ExceptionHandler<T> exceptionHandler )
-        throws T
-    {
-        return invoke( object.getClass(), object, method, exceptionHandler );
-    }
-
-    static <T extends Exception> Object invoke( Class<?> objectClazz, Object object, String method,
-                                                ExceptionHandler<T> exceptionHandler )
-        throws T
-    {
-        try
-        {
-            return objectClazz.getMethod( method ).invoke( object );
-        }
-        catch ( ReflectiveOperationException e )
-        {
-            throw exceptionHandler.create( e.getMessage(), e );
-        }
-    }
-
-    static Object invoke( Object object, String method, Class<?> clazz, Object arg )
-        throws DependencyGraphBuilderException
-    {
-        try
-        {
-            final Class<?> objectClazz = object.getClass();
-            return objectClazz.getMethod( method, clazz ).invoke( object, arg );
-        }
-        catch ( ReflectiveOperationException e )
-        {
-            throw new DependencyGraphBuilderException( e.getMessage(), e );
-        }
-    }
-    
-    static <T extends Exception> Object invoke( Class<?> objectClazz, String staticMethod,
-                                                               Class<?> argClazz, Object arg,
-                                                               ExceptionHandler<T> exceptionHandler )
-        throws T
-    {
-        try
-        {
-            return objectClazz.getMethod( staticMethod, argClazz ).invoke( null, arg );
-        }
-        catch ( ReflectiveOperationException e )
-        {
-            throw exceptionHandler.create( e.getMessage(), e );
-        }
-    }
-
-    static <T extends Exception> Object invoke( Class<?> objectClazz, String staticMethod, Class<?> argClazz1,
-                                                Class<?> argClazz2, Object arg1, Object arg2,
-                                                ExceptionHandler<T> exceptionHandler )
-        throws T
-    {
-        try
-        {
-            return objectClazz.getMethod( staticMethod, argClazz1, argClazz2 ).invoke( null, arg1, arg2 );
-        }
-        catch ( ReflectiveOperationException e )
-        {
-            throw exceptionHandler.create( e.getMessage(), e );
-        }
-    }
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyCollectorBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyCollectorBuilder.java
index 73d06de..f8517e4 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyCollectorBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyCollectorBuilder.java
@@ -40,6 +40,7 @@ import org.codehaus.plexus.component.annotations.Requirement;
 import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.eclipse.aether.DefaultRepositorySystemSession;
 import org.eclipse.aether.RepositorySystem;
+import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
 import org.eclipse.aether.collection.CollectRequest;
 import org.eclipse.aether.collection.CollectResult;
@@ -60,6 +61,8 @@ import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
 import org.eclipse.aether.util.graph.visitor.TreeDependencyVisitor;
 import org.eclipse.aether.version.VersionConstraint;
 
+import static org.apache.maven.RepositoryUtils.toArtifact;
+
 /**
  * Project dependency raw dependency collector API, abstracting Maven 3.1+'s Aether implementation.
  * 
@@ -93,9 +96,15 @@ public class Maven31DependencyCollectorBuilder
             Artifact projectArtifact = project.getArtifact();
             List<ArtifactRepository> remoteArtifactRepositories = project.getRemoteArtifactRepositories();
 
-            DefaultRepositorySystemSession repositorySession =
-                (DefaultRepositorySystemSession) Invoker.invoke( buildingRequest, "getRepositorySession",
-                                                                 exceptionHandler );
+            RepositorySystemSession repositorySession;
+            try
+            {
+                repositorySession = buildingRequest.getRepositorySession();
+            }
+            catch ( Exception e )
+            {
+                throw exceptionHandler.create( e.getMessage(), e );
+            }
 
             session = new DefaultRepositorySystemSession( repositorySession );
 
@@ -113,17 +122,25 @@ public class Maven31DependencyCollectorBuilder
             session.setConfigProperty( ConflictResolver.CONFIG_PROP_VERBOSE, true );
             session.setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, true );
 
-            org.eclipse.aether.artifact.Artifact aetherArtifact =
-                (org.eclipse.aether.artifact.Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
-                                                                       Artifact.class, projectArtifact,
-                                                                       exceptionHandler );
+            org.eclipse.aether.artifact.Artifact aetherArtifact;
+            try
+            {
+                aetherArtifact = RepositoryUtils.toArtifact( projectArtifact );
+            }
+            catch ( Exception e )
+            {
+                throw exceptionHandler.create( e.getMessage(), e );
+            }
 
-            @SuppressWarnings( "unchecked" )
-            List<org.eclipse.aether.repository.RemoteRepository> aetherRepos =
-                (List<org.eclipse.aether.repository.RemoteRepository>) Invoker.invoke( RepositoryUtils.class, "toRepos",
-                                                                                       List.class,
-                                                                                       remoteArtifactRepositories,
-                                                                                       exceptionHandler );
+            List<org.eclipse.aether.repository.RemoteRepository> aetherRepos;
+            try
+            {
+                aetherRepos = RepositoryUtils.toRepos( remoteArtifactRepositories );
+            }
+            catch ( Exception e )
+            {
+                throw exceptionHandler.create( e.getMessage(), e );
+            }
 
             CollectRequest collectRequest = new CollectRequest();
             collectRequest.setRootArtifact( aetherArtifact );
@@ -202,8 +219,7 @@ public class Maven31DependencyCollectorBuilder
     {
         for ( Dependency dependency : project.getDependencies() )
         {
-            org.eclipse.aether.graph.Dependency aetherDep = toAetherDependency( stereotypes, dependency );
-            collectRequest.addDependency( aetherDep );
+            collectRequest.addDependency( toAetherDependency( stereotypes, dependency ) );
         }
     }
 
@@ -212,34 +228,24 @@ public class Maven31DependencyCollectorBuilder
                                                                     Dependency dependency )
         throws DependencyCollectorBuilderException
     {
-        return (org.eclipse.aether.graph.Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency",
-                                                              Dependency.class,
-                                                              ArtifactTypeRegistry.class,
-                                                              dependency, stereotypes, exceptionHandler );
-    }
-    // CHECKSTYLE_ON: LineLength
-
-    private Artifact getDependencyArtifact( org.eclipse.aether.graph.Dependency dep )
-    {
-        org.eclipse.aether.artifact.Artifact artifact = dep.getArtifact();
-
         try
         {
-            Artifact mavenArtifact =
-                (Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
-                                           org.eclipse.aether.artifact.Artifact.class, artifact, exceptionHandler );
-
-            mavenArtifact.setScope( dep.getScope() );
-            mavenArtifact.setOptional( dep.isOptional() );
-
-            return mavenArtifact;
+            return RepositoryUtils.toDependency( dependency, stereotypes );
         }
-        catch ( DependencyCollectorBuilderException e )
+        catch ( Exception e )
         {
-            // ReflectionException should not happen
-            throw new RuntimeException( e.getMessage(), e );
+            throw exceptionHandler.create( e.getMessage(), e );
         }
     }
+    // CHECKSTYLE_ON: LineLength
+
+    private Artifact getDependencyArtifact( org.eclipse.aether.graph.Dependency dep )
+    {
+        Artifact mavenArtifact = toArtifact( dep.getArtifact() );
+        mavenArtifact.setScope( dep.getScope() );
+        mavenArtifact.setOptional( dep.isOptional() );
+        return mavenArtifact;
+    }
 
     private DependencyNode buildDependencyNode( DependencyNode parent, org.eclipse.aether.graph.DependencyNode node,
                                                 Artifact artifact, ArtifactFilter filter )
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java
index bdecb91..59c678d 100644
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java
+++ b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven31DependencyGraphBuilder.java
@@ -19,13 +19,13 @@ package org.apache.maven.shared.dependency.graph.internal;
  * under the License.
  */
 
+import static org.apache.maven.RepositoryUtils.toArtifact;
 import static org.eclipse.aether.util.graph.manager.DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-import org.apache.maven.RepositoryUtils;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
 import org.apache.maven.project.DefaultDependencyResolutionRequest;
@@ -44,7 +44,6 @@ import org.codehaus.plexus.logging.AbstractLogEnabled;
 import org.eclipse.aether.DefaultRepositorySystemSession;
 import org.eclipse.aether.RepositorySystemSession;
 import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.graph.DependencyFilter;
 import org.eclipse.aether.graph.Exclusion;
 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
 import org.eclipse.aether.version.VersionConstraint;
@@ -64,11 +63,8 @@ public class Maven31DependencyGraphBuilder
     @Requirement
     private ProjectDependenciesResolver resolver;
 
-    private final ExceptionHandler<DependencyGraphBuilderException> exceptionHandler;
-    
     public Maven31DependencyGraphBuilder()
     {
-        this.exceptionHandler = DependencyGraphBuilderException::new;
     }
 
     /**
@@ -85,10 +81,7 @@ public class Maven31DependencyGraphBuilder
     {
         MavenProject project = buildingRequest.getProject();
 
-        RepositorySystemSession session =
-            (RepositorySystemSession) Invoker.invoke( buildingRequest, "getRepositorySession", exceptionHandler );
-
-        
+        RepositorySystemSession session = buildingRequest.getRepositorySession();
         if ( Boolean.TRUE != session.getConfigProperties().get( NODE_DATA_PREMANAGED_VERSION ) )
         {
             DefaultRepositorySystemSession newSession = new DefaultRepositorySystemSession( session );
@@ -98,17 +91,13 @@ public class Maven31DependencyGraphBuilder
 
         final DependencyResolutionRequest request = new DefaultDependencyResolutionRequest();
         request.setMavenProject( project );
-        Invoker.invoke( request, "setRepositorySession", RepositorySystemSession.class, session );
+        request.setRepositorySession( session );
         // only download the poms, not the artifacts
-        DependencyFilter collectFilter = ( node, parents ) -> false;
-        Invoker.invoke( request, "setResolutionFilter", DependencyFilter.class, collectFilter );
+        request.setResolutionFilter( ( node, parents ) -> false );
 
-        final DependencyResolutionResult result = resolveDependencies( request );
-        org.eclipse.aether.graph.DependencyNode graph =
-            (org.eclipse.aether.graph.DependencyNode) Invoker.invoke( DependencyResolutionResult.class, result,
-                                                                      "getDependencyGraph", exceptionHandler );
+        DependencyResolutionResult result = resolveDependencies( request );
 
-        return buildDependencyNode( null, graph, project.getArtifact(), filter );
+        return buildDependencyNode( null, result.getDependencyGraph(), project.getArtifact(), filter );
     }
 
     private DependencyResolutionResult resolveDependencies( DependencyResolutionRequest request )
@@ -125,27 +114,6 @@ public class Maven31DependencyGraphBuilder
         }
     }
 
-    private Artifact getDependencyArtifact( Dependency dep )
-    {
-        org.eclipse.aether.artifact.Artifact artifact = dep.getArtifact();
-
-        try
-        {
-            Artifact mavenArtifact = (Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
-                                              org.eclipse.aether.artifact.Artifact.class, artifact, exceptionHandler );
-
-            mavenArtifact.setScope( dep.getScope() );
-            mavenArtifact.setOptional( dep.isOptional() );
-
-            return mavenArtifact;
-        }
-        catch ( DependencyGraphBuilderException e )
-        {
-            // ReflectionException should not happen
-            throw new RuntimeException( e.getMessage(), e );
-        }
-    }
-
     private DependencyNode buildDependencyNode( DependencyNode parent, org.eclipse.aether.graph.DependencyNode node,
                                                 Artifact artifact, ArtifactFilter filter )
     {
@@ -174,11 +142,14 @@ public class Maven31DependencyGraphBuilder
         List<DependencyNode> nodes = new ArrayList<>( node.getChildren().size() );
         for ( org.eclipse.aether.graph.DependencyNode child : node.getChildren() )
         {
-            Artifact childArtifact = getDependencyArtifact( child.getDependency() );
+            Dependency dep = child.getDependency();
+            Artifact mavenArtifact = toArtifact( dep.getArtifact() );
+            mavenArtifact.setScope( dep.getScope() );
+            mavenArtifact.setOptional( dep.isOptional() );
 
-            if ( ( filter == null ) || filter.include( childArtifact ) )
+            if ( ( filter == null ) || filter.include( mavenArtifact ) )
             {
-                nodes.add( buildDependencyNode( current, child, childArtifact, filter ) );
+                nodes.add( buildDependencyNode( current, child, mavenArtifact, filter ) );
             }
         }
 
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyCollectorBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyCollectorBuilder.java
deleted file mode 100644
index 2a3a555..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyCollectorBuilder.java
+++ /dev/null
@@ -1,321 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.maven.RepositoryUtils;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.repository.ArtifactRepository;
-import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.model.Dependency;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.ProjectBuildingRequest;
-import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilder;
-import org.apache.maven.shared.dependency.graph.DependencyCollectorBuilderException;
-import org.apache.maven.shared.dependency.graph.DependencyNode;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver;
-import org.apache.maven.shared.dependency.graph.internal.maven30.JavaScopeDeriver;
-import org.apache.maven.shared.dependency.graph.internal.maven30.Maven3DirectScopeDependencySelector;
-import org.apache.maven.shared.dependency.graph.internal.maven30.NearestVersionSelector;
-import org.apache.maven.shared.dependency.graph.internal.maven30.SimpleOptionalitySelector;
-import org.apache.maven.shared.dependency.graph.internal.maven30.VerboseJavaScopeSelector;
-import org.codehaus.plexus.component.annotations.Component;
-import org.codehaus.plexus.component.annotations.Requirement;
-import org.codehaus.plexus.logging.AbstractLogEnabled;
-import org.sonatype.aether.RepositorySystem;
-import org.sonatype.aether.RepositorySystemSession;
-import org.sonatype.aether.artifact.ArtifactTypeRegistry;
-import org.sonatype.aether.collection.CollectRequest;
-import org.sonatype.aether.collection.CollectResult;
-import org.sonatype.aether.collection.DependencyCollectionException;
-import org.sonatype.aether.collection.DependencyGraphTransformer;
-import org.sonatype.aether.collection.DependencySelector;
-import org.sonatype.aether.graph.DependencyVisitor;
-import org.sonatype.aether.graph.Exclusion;
-import org.sonatype.aether.util.DefaultRepositorySystemSession;
-import org.sonatype.aether.util.artifact.JavaScopes;
-import org.sonatype.aether.util.graph.TreeDependencyVisitor;
-import org.sonatype.aether.util.graph.selector.AndDependencySelector;
-import org.sonatype.aether.util.graph.selector.ExclusionDependencySelector;
-import org.sonatype.aether.util.graph.selector.OptionalDependencySelector;
-import org.sonatype.aether.version.VersionConstraint;
-
-/**
- * Project dependency raw dependency collector API, abstracting Maven 3's Aether implementation.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-@Component( role = DependencyCollectorBuilder.class, hint = "maven3" )
-public class Maven3DependencyCollectorBuilder
-    extends AbstractLogEnabled
-    implements DependencyCollectorBuilder
-{
-    @Requirement
-    private RepositorySystem repositorySystem;
-    
-    private final ExceptionHandler<DependencyCollectorBuilderException> exceptionHandler;
-    
-    public Maven3DependencyCollectorBuilder()
-    {
-        this.exceptionHandler = DependencyCollectorBuilderException::new;
-    }
-
-    @Override
-    public DependencyNode collectDependencyGraph( ProjectBuildingRequest buildingRequest, ArtifactFilter filter )
-        throws DependencyCollectorBuilderException
-    {
-        try
-        {
-            MavenProject project = buildingRequest.getProject();
-
-            Artifact projectArtifact = project.getArtifact();
-            List<ArtifactRepository> remoteArtifactRepositories = project.getRemoteArtifactRepositories();
-
-            // throws ClassCastException (classloading issues?)
-            // DefaultRepositorySystemSession repositorySystemSession =
-            // (DefaultRepositorySystemSession) Invoker.invoke( buildingRequest, "getRepositorySession" );
-            RepositorySystemSession repositorySystemSession = buildingRequest.getRepositorySession();
-
-            DefaultRepositorySystemSession session = new DefaultRepositorySystemSession( repositorySystemSession );
-
-            DependencyGraphTransformer transformer =
-                new ConflictResolver( new NearestVersionSelector(), new VerboseJavaScopeSelector(),
-                                      new SimpleOptionalitySelector(), new JavaScopeDeriver() );
-            session.setDependencyGraphTransformer( transformer );
-
-            DependencySelector depFilter =
-                new AndDependencySelector( new Maven3DirectScopeDependencySelector( JavaScopes.TEST ),
-                                           new OptionalDependencySelector(), 
-                                           new ExclusionDependencySelector() );
-            session.setDependencySelector( depFilter );
-
-            session.setConfigProperty( ConflictResolver.CONFIG_PROP_VERBOSE, true );
-            session.setConfigProperty( "aether.dependencyManager.verbose", true );
-
-            org.sonatype.aether.artifact.Artifact aetherArtifact =
-                (org.sonatype.aether.artifact.Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
-                                                                        Artifact.class, projectArtifact,
-                                                                        exceptionHandler );
-
-            @SuppressWarnings( "unchecked" )
-            List<org.sonatype.aether.repository.RemoteRepository> aetherRepos =
-                (List<org.sonatype.aether.repository.RemoteRepository>) Invoker.invoke( RepositoryUtils.class,
-                                                                                        "toRepos", List.class,
-                                                                                        remoteArtifactRepositories,
-                                                                                        exceptionHandler );
-
-            CollectRequest collectRequest = new CollectRequest();
-            collectRequest.setRoot( new org.sonatype.aether.graph.Dependency( aetherArtifact, "" ) );
-            collectRequest.setRepositories( aetherRepos );
-
-            org.sonatype.aether.artifact.ArtifactTypeRegistry stereotypes = session.getArtifactTypeRegistry();
-            collectDependencyList( collectRequest, project, stereotypes );
-            collectManagedDependencyList( collectRequest, project, stereotypes );
-
-            CollectResult collectResult = repositorySystem.collectDependencies( session, collectRequest );
-
-            org.sonatype.aether.graph.DependencyNode rootNode = collectResult.getRoot();
-
-            if ( getLogger().isDebugEnabled() )
-            {
-                logTree( rootNode );
-            }
-
-            return buildDependencyNode( null, rootNode, projectArtifact, filter );
-        }
-        catch ( DependencyCollectionException e )
-        {
-            throw new DependencyCollectorBuilderException( "Could not collect dependencies: " + e.getResult(), e );
-        }
-    }
-
-    private void logTree( org.sonatype.aether.graph.DependencyNode rootNode )
-    {
-        // print the node tree with its associated data Map
-        rootNode.accept( new TreeDependencyVisitor( new DependencyVisitor()
-        {
-            String indent = "";
-
-            @Override
-            public boolean visitEnter( org.sonatype.aether.graph.DependencyNode dependencyNode )
-            {
-                StringBuilder sb = new StringBuilder();
-                sb.append( indent ).append( "Aether node: " ).append( dependencyNode );
-                if ( !dependencyNode.getData().isEmpty() )
-                {
-                    sb.append( "data map: " ).append( dependencyNode.getData() );
-                }
-                if ( dependencyNode.getPremanagedVersion() != null && !dependencyNode.getPremanagedVersion().isEmpty() )
-                {
-                    sb.append( "Premanaged.version: " ).append( dependencyNode.getPremanagedVersion() );
-                }
-                if ( dependencyNode.getPremanagedScope() != null && !dependencyNode.getPremanagedScope().isEmpty() )
-                {
-                    sb.append( "Premanaged.scope: " ).append( dependencyNode.getPremanagedScope() );
-                }
-                getLogger().debug( sb.toString() );
-                indent += "    ";
-                return true;
-            }
-
-            @Override
-            public boolean visitLeave( org.sonatype.aether.graph.DependencyNode dependencyNode )
-            {
-                indent = indent.substring( 0, indent.length() - 4 );
-                return true;
-            }
-        } ) );
-    }
-
-    private void collectManagedDependencyList( CollectRequest collectRequest, MavenProject project,
-                                               ArtifactTypeRegistry stereotypes )
-        throws DependencyCollectorBuilderException
-    {
-        if ( project.getDependencyManagement() != null )
-        {
-            for ( Dependency dependency : project.getDependencyManagement().getDependencies() )
-            {
-                org.sonatype.aether.graph.Dependency aetherDep = toAetherDependency( stereotypes, dependency );
-                collectRequest.addManagedDependency( aetherDep );
-            }
-        }
-    }
-
-    private void collectDependencyList( CollectRequest collectRequest, MavenProject project,
-                                        org.sonatype.aether.artifact.ArtifactTypeRegistry stereotypes )
-        throws DependencyCollectorBuilderException
-    {
-        for ( Dependency dependency : project.getDependencies() )
-        {
-            org.sonatype.aether.graph.Dependency aetherDep = toAetherDependency( stereotypes, dependency );
-            collectRequest.addDependency( aetherDep );
-        }
-    }
-
-    // CHECKSTYLE_OFF: LineLength
-    private org.sonatype.aether.graph.Dependency toAetherDependency( org.sonatype.aether.artifact.ArtifactTypeRegistry stereotypes,
-                                                                    Dependency dependency )
-        throws DependencyCollectorBuilderException
-    {
-        return (org.sonatype.aether.graph.Dependency) Invoker.invoke( RepositoryUtils.class, "toDependency",
-                                                              Dependency.class,
-                                                               ArtifactTypeRegistry.class,
-                                                              dependency, stereotypes, exceptionHandler );
-    }
-    // CHECKSTYLE_ON: LineLength
-
-    private Artifact getDependencyArtifact( org.sonatype.aether.graph.Dependency dep )
-    {
-        org.sonatype.aether.artifact.Artifact artifact = dep.getArtifact();
-
-        try
-        {
-            Artifact mavenArtifact =
-                (Artifact) Invoker.invoke( RepositoryUtils.class, "toArtifact",
-                                           org.sonatype.aether.artifact.Artifact.class, artifact, exceptionHandler );
-
-            mavenArtifact.setScope( dep.getScope() );
-            mavenArtifact.setOptional( dep.isOptional() );
-
-            return mavenArtifact;
-        }
-        catch ( DependencyCollectorBuilderException e )
-        {
-            // ReflectionException should not happen
-            throw new RuntimeException( e.getMessage(), e );
-        }
-    }
-
-    private DependencyNode buildDependencyNode( DependencyNode parent, org.sonatype.aether.graph.DependencyNode node,
-                                                Artifact artifact, ArtifactFilter filter )
-    {
-        String premanagedVersion = node.getPremanagedVersion();
-        String premanagedScope = node.getPremanagedScope();
-
-        Boolean optional = null;
-        if ( node.getDependency() != null )
-        {
-            optional = node.getDependency().isOptional();
-        }
-
-        List<org.apache.maven.model.Exclusion> exclusions = null;
-        if ( node.getDependency() != null )
-        {
-            exclusions = new ArrayList<>( node.getDependency().getExclusions().size() );
-            for ( Exclusion exclusion : node.getDependency().getExclusions() )
-            {
-                org.apache.maven.model.Exclusion modelExclusion = new org.apache.maven.model.Exclusion();
-                modelExclusion.setGroupId( exclusion.getGroupId() );
-                modelExclusion.setArtifactId( exclusion.getArtifactId() );
-                exclusions.add( modelExclusion );
-            }
-        }
-
-        org.sonatype.aether.graph.DependencyNode winner =
-            (org.sonatype.aether.graph.DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER );
-        String winnerVersion = null;
-        String ignoredScope = null;
-        if ( winner != null )
-        {
-            winnerVersion = winner.getVersion().toString();
-        }
-        else
-        {
-            ignoredScope = (String) node.getData().get( VerboseJavaScopeSelector.REDUCED_SCOPE );
-        }
-
-        ConflictData data = new ConflictData( winnerVersion, ignoredScope );
-
-        VerboseDependencyNode current =
-            new VerboseDependencyNode( parent, artifact, premanagedVersion, premanagedScope,
-                                       getVersionSelectedFromRange( node.getVersionConstraint() ), optional, exclusions,
-                                       data );
-
-        List<DependencyNode> nodes = new ArrayList<>( node.getChildren().size() );
-        for ( org.sonatype.aether.graph.DependencyNode child : node.getChildren() )
-        {
-            Artifact childArtifact = getDependencyArtifact( child.getDependency() );
-
-            if ( ( filter == null ) || filter.include( childArtifact ) )
-            {
-                nodes.add( buildDependencyNode( current, child, childArtifact, filter ) );
-            }
-        }
-
-        current.setChildren( Collections.unmodifiableList( nodes ) );
-
-        return current;
-    }
-
-    private String getVersionSelectedFromRange( VersionConstraint constraint )
-    {
-        if ( ( constraint == null ) || ( constraint.getVersion() != null ) || ( constraint.getRanges().isEmpty() ) )
-        {
-            return null;
-        }
-
-        return constraint.getRanges().iterator().next().toString();
-    }
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java
deleted file mode 100644
index 2ec8f94..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/Maven3DependencyGraphBuilder.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.maven.RepositoryUtils;
-import org.apache.maven.artifact.Artifact;
-import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
-import org.apache.maven.project.DefaultDependencyResolutionRequest;
-import org.apache.maven.project.DependencyResolutionException;
-import org.apache.maven.project.DependencyResolutionRequest;
-import org.apache.maven.project.DependencyResolutionResult;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.ProjectBuildingRequest;
-import org.apache.maven.project.ProjectDependenciesResolver;
-import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
-import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
-import org.apache.maven.shared.dependency.graph.DependencyNode;
-import org.codehaus.plexus.component.annotations.Component;
-import org.codehaus.plexus.component.annotations.Requirement;
-import org.codehaus.plexus.logging.AbstractLogEnabled;
-import org.sonatype.aether.graph.DependencyFilter;
-import org.sonatype.aether.graph.Dependency;
-import org.sonatype.aether.version.VersionConstraint;
-
-/**
- * Wrapper around Maven 3 dependency resolver.
- *
- * @see ProjectDependenciesResolver
- * @author Hervé Boutemy
- * @since 2.0
- */
-@Component( role = DependencyGraphBuilder.class, hint = "maven3" )
-public class Maven3DependencyGraphBuilder
-    extends AbstractLogEnabled
-    implements DependencyGraphBuilder
-{
-    @Requirement
-    private ProjectDependenciesResolver resolver;
-
-    /**
-     * Builds the dependency graph for Maven 3.
-     *
-     * @param buildingRequest the buildingRequest
-     * @param filter artifact filter (can be <code>null</code>)
-     * @return DependencyNode containing the dependency graph.
-     * @throws DependencyGraphBuilderException if some of the dependencies could not be resolved.
-     */
-    @Override
-    public DependencyNode buildDependencyGraph( ProjectBuildingRequest buildingRequest, ArtifactFilter filter )
-        throws DependencyGraphBuilderException
-    {
-        MavenProject project = buildingRequest.getProject();
-
-        DependencyResolutionRequest request =
-            new DefaultDependencyResolutionRequest( project, buildingRequest.getRepositorySession() );
-
-        // only download the poms, not the artifacts
-        DependencyFilter collectFilter = ( node, parents ) -> false;
-        request.setResolutionFilter( collectFilter );
-
-        DependencyResolutionResult result = resolveDependencies( request );
-
-        return buildDependencyNode( null, result.getDependencyGraph(), project.getArtifact(), filter );
-    }
-
-    private DependencyResolutionResult resolveDependencies( DependencyResolutionRequest request )
-        throws DependencyGraphBuilderException
-    {
-        try
-        {
-            return resolver.resolve( request );
-        }
-        catch ( DependencyResolutionException e )
-        {
-            throw new DependencyGraphBuilderException( "Could not resolve following dependencies: "
-                + e.getResult().getUnresolvedDependencies(), e );
-        }
-    }
-
-    private Artifact getDependencyArtifact( Dependency dep )
-    {
-        Artifact mavenArtifact = RepositoryUtils.toArtifact( dep.getArtifact() );
-
-        mavenArtifact.setScope( dep.getScope() );
-        mavenArtifact.setOptional( dep.isOptional() );
-
-        return mavenArtifact;
-    }
-
-    private DependencyNode buildDependencyNode( DependencyNode parent, org.sonatype.aether.graph.DependencyNode node,
-                                                Artifact artifact, ArtifactFilter filter )
-    {
-        DefaultDependencyNode current =
-            new DefaultDependencyNode( parent, artifact,
-                                       null /* node.getPremanagedVersion() */,
-                                       null /* node.getPremanagedScope() */,
-                                       getVersionSelectedFromRange( node.getVersionConstraint() ) );
-
-        List<DependencyNode> nodes = new ArrayList<>( node.getChildren().size() );
-        for ( org.sonatype.aether.graph.DependencyNode child : node.getChildren() )
-        {
-            Artifact childArtifact = getDependencyArtifact( child.getDependency() );
-
-            if ( ( filter == null ) || filter.include( childArtifact ) )
-            {
-                nodes.add( buildDependencyNode( current, child, childArtifact, filter ) );
-            }
-        }
-
-        current.setChildren( Collections.unmodifiableList( nodes ) );
-
-        return current;
-    }
-
-    private String getVersionSelectedFromRange( VersionConstraint constraint )
-    {
-        if ( ( constraint == null ) || ( constraint.getVersion() != null ) )
-        {
-            return null;
-        }
-
-        StringBuilder sb = new StringBuilder();
-        for ( org.sonatype.aether.version.VersionRange range : constraint.getRanges() )
-        {
-            if ( sb.length() > 0 )
-            {
-                sb.append( ',' );
-            }
-            sb.append( range );
-        }
-
-        return sb.toString();
-    }
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ConflictIdSorter.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ConflictIdSorter.java
deleted file mode 100644
index 35cb5a8..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ConflictIdSorter.java
+++ /dev/null
@@ -1,370 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.sonatype.aether.RepositoryException;
-import org.sonatype.aether.collection.DependencyGraphTransformationContext;
-import org.sonatype.aether.collection.DependencyGraphTransformer;
-import org.sonatype.aether.graph.DependencyNode;
-import org.sonatype.aether.util.graph.transformer.ConflictMarker;
-import org.sonatype.aether.util.graph.transformer.TransformationContextKeys;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public final class ConflictIdSorter
-    implements DependencyGraphTransformer
-{
-
-    public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
-        throws RepositoryException
-    {
-        Map<?, ?> conflictIds = (Map<?, ?>) context.get( TransformationContextKeys.CONFLICT_IDS );
-        if ( conflictIds == null )
-        {
-            ConflictMarker marker = new ConflictMarker();
-            marker.transformGraph( node, context );
-
-            conflictIds = (Map<?, ?>) context.get( TransformationContextKeys.CONFLICT_IDS );
-        }
-
-//        @SuppressWarnings( "unchecked" )
-//        Map<String, Object> stats = (Map<String, Object>) context.get( TransformationContextKeys.STATS );
-//        long time1 = System.currentTimeMillis();
-
-        Map<Object, ConflictId> ids = new LinkedHashMap<>( 256 );
-
-        // CHECKSTYLE_OFF: AvoidNestedBlocks
-        {
-            ConflictId id = null;
-            Object key = conflictIds.get( node );
-            if ( key != null )
-            {
-                id = new ConflictId( key, 0 );
-                ids.put( key, id );
-            }
-
-            Map<DependencyNode, Object> visited = new IdentityHashMap<>( conflictIds.size() );
-
-            buildConflitIdDAG( ids, node, id, 0, visited, conflictIds );
-        }
-        // CHECKSTYLE_NO: AvoidNestedBlocks
-
-//        long time2 = System.currentTimeMillis();
-
-        topsortConflictIds( ids.values(), context );
-//        int cycles = topsortConflictIds( ids.values(), context );
-
-//        if ( stats != null )
-//        {
-//            long time3 = System.currentTimeMillis();
-//            stats.put( "ConflictIdSorter.graphTime", time2 - time1 );
-//            stats.put( "ConflictIdSorter.topsortTime", time3 - time2 );
-//            stats.put( "ConflictIdSorter.conflictIdCount", ids.size() );
-//            stats.put( "ConflictIdSorter.conflictIdCycleCount", cycles );
-//        }
-
-        return node;
-    }
-
-    private void buildConflitIdDAG( Map<Object, ConflictId> ids, DependencyNode node, ConflictId id, int depth,
-                                    Map<DependencyNode, Object> visited, Map<?, ?> conflictIds )
-    {
-        if ( visited.put( node, Boolean.TRUE ) != null )
-        {
-            return;
-        }
-
-        depth++;
-
-        for ( DependencyNode child : node.getChildren() )
-        {
-            Object key = conflictIds.get( child );
-            ConflictId childId = ids.get( key );
-            if ( childId == null )
-            {
-                childId = new ConflictId( key, depth );
-                ids.put( key, childId );
-            }
-            else
-            {
-                childId.pullup( depth );
-            }
-
-            if ( id != null )
-            {
-                id.add( childId );
-            }
-
-            buildConflitIdDAG( ids, child, childId, depth, visited, conflictIds );
-        }
-    }
-
-    private int topsortConflictIds( Collection<ConflictId> conflictIds, DependencyGraphTransformationContext context )
-    {
-        List<Object> sorted = new ArrayList<>( conflictIds.size() );
-
-        RootQueue roots = new RootQueue( conflictIds.size() / 2 );
-        for ( ConflictId id : conflictIds )
-        {
-            if ( id.inDegree <= 0 )
-            {
-                roots.add( id );
-            }
-        }
-
-        processRoots( sorted, roots );
-
-        boolean cycle = sorted.size() < conflictIds.size();
-
-        while ( sorted.size() < conflictIds.size() )
-        {
-            // cycle -> deal gracefully with nodes still having positive in-degree
-
-            ConflictId nearest = null;
-            for ( ConflictId id : conflictIds )
-            {
-                if ( id.inDegree <= 0 )
-                {
-                    continue;
-                }
-                if ( nearest == null || id.minDepth < nearest.minDepth
-                    || ( id.minDepth == nearest.minDepth && id.inDegree < nearest.inDegree ) )
-                {
-                    nearest = id;
-                }
-            }
-
-            nearest.inDegree = 0;
-            roots.add( nearest );
-
-            processRoots( sorted, roots );
-        }
-
-        Collection<Collection<Object>> cycles = Collections.emptySet();
-        if ( cycle )
-        {
-            cycles = findCycles( conflictIds );
-        }
-
-        context.put( TransformationContextKeys.SORTED_CONFLICT_IDS, sorted );
-        context.put( TransformationContextKeys.CYCLIC_CONFLICT_IDS, cycles );
-
-        return cycles.size();
-    }
-
-    private void processRoots( List<Object> sorted, RootQueue roots )
-    {
-        while ( !roots.isEmpty() )
-        {
-            ConflictId root = roots.remove();
-
-            sorted.add( root.key );
-
-            for ( ConflictId child : root.children )
-            {
-                child.inDegree--;
-                if ( child.inDegree == 0 )
-                {
-                    roots.add( child );
-                }
-            }
-        }
-    }
-
-    private Collection<Collection<Object>> findCycles( Collection<ConflictId> conflictIds )
-    {
-        Collection<Collection<Object>> cycles = new HashSet<>();
-
-        Map<Object, Integer> stack = new HashMap<>( 128 );
-        Map<ConflictId, Object> visited = new IdentityHashMap<>( conflictIds.size() );
-        for ( ConflictId id : conflictIds )
-        {
-            findCycles( id, visited, stack, cycles );
-        }
-
-        return cycles;
-    }
-
-    private void findCycles( ConflictId id, Map<ConflictId, Object> visited, Map<Object, Integer> stack,
-                             Collection<Collection<Object>> cycles )
-    {
-        Integer depth = stack.put( id.key, stack.size() );
-        if ( depth != null )
-        {
-            stack.put( id.key, depth );
-            Collection<Object> cycle = new HashSet<>();
-            for ( Map.Entry<Object, Integer> entry : stack.entrySet() )
-            {
-                if ( entry.getValue() >= depth )
-                {
-                    cycle.add( entry.getKey() );
-                }
-            }
-            cycles.add( cycle );
-        }
-        else
-        {
-            if ( visited.put( id, Boolean.TRUE ) == null )
-            {
-                for ( ConflictId childId : id.children )
-                {
-                    findCycles( childId, visited, stack, cycles );
-                }
-            }
-            stack.remove( id.key );
-        }
-    }
-
-    static final class ConflictId
-    {
-
-        final Object key;
-
-        Collection<ConflictId> children = Collections.emptySet();
-
-        int inDegree;
-
-        int minDepth;
-
-        ConflictId( Object key, int depth )
-        {
-            this.key = key;
-            this.minDepth = depth;
-        }
-
-        public void add( ConflictId child )
-        {
-            if ( children.isEmpty() )
-            {
-                children = new HashSet<>();
-            }
-            if ( children.add( child ) )
-            {
-                child.inDegree++;
-            }
-        }
-
-        public void pullup( int depth )
-        {
-            if ( depth < minDepth )
-            {
-                minDepth = depth;
-                depth++;
-                for ( ConflictId child : children )
-                {
-                    child.pullup( depth );
-                }
-            }
-        }
-
-        @Override
-        public boolean equals( Object obj )
-        {
-            if ( this == obj )
-            {
-                return true;
-            }
-            else if ( !( obj instanceof ConflictId ) )
-            {
-                return false;
-            }
-            ConflictId that = (ConflictId) obj;
-            return this.key.equals( that.key );
-        }
-
-        @Override
-        public int hashCode()
-        {
-            return key.hashCode();
-        }
-
-        @Override
-        public String toString()
-        {
-            return key + " @ " + minDepth + " <" + inDegree;
-        }
-
-    }
-
-    static final class RootQueue
-    {
-
-        private int nextOut;
-
-        private int nextIn;
-
-        private ConflictId[] ids;
-
-        RootQueue( int capacity )
-        {
-            ids = new ConflictId[capacity + 16];
-        }
-
-        boolean isEmpty()
-        {
-            return nextOut >= nextIn;
-        }
-
-        void add( ConflictId id )
-        {
-            if ( nextOut >= nextIn && nextOut > 0 )
-            {
-                nextIn -= nextOut;
-                nextOut = 0;
-            }
-            if ( nextIn >= ids.length )
-            {
-                ConflictId[] tmp = new ConflictId[ids.length + ids.length / 2 + 16];
-                System.arraycopy( ids, nextOut, tmp, 0, nextIn - nextOut );
-                ids = tmp;
-                nextIn -= nextOut;
-                nextOut = 0;
-            }
-            int i;
-            for ( i = nextIn - 1; i >= nextOut && id.minDepth < ids[i].minDepth; i-- )
-            {
-                ids[i + 1] = ids[i];
-            }
-            ids[i + 1] = id;
-            nextIn++;
-        }
-
-        ConflictId remove()
-        {
-            return ids[nextOut++];
-        }
-
-    }
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ConflictResolver.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ConflictResolver.java
deleted file mode 100644
index 329c028..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ConflictResolver.java
+++ /dev/null
@@ -1,1314 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.sonatype.aether.RepositoryException;
-import org.sonatype.aether.artifact.Artifact;
-import org.sonatype.aether.collection.DependencyGraphTransformationContext;
-import org.sonatype.aether.collection.DependencyGraphTransformer;
-import org.sonatype.aether.graph.Dependency;
-import org.sonatype.aether.graph.DependencyNode;
-import org.sonatype.aether.util.ConfigUtils;
-import org.sonatype.aether.util.graph.DefaultDependencyNode;
-import org.sonatype.aether.util.graph.transformer.TransformationContextKeys;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public final class ConflictResolver
-    implements DependencyGraphTransformer
-{
-
-    /**
-     * The key in the repository session's {@link org.sonatype.aether.RepositorySystemSession#getConfigProperties()
-     * configuration properties} used to store a {@link Boolean} flag controlling the transformer's verbose mode.
-     */
-    public static final String CONFIG_PROP_VERBOSE = "aether.conflictResolver.verbose";
-
-    /**
-     * The key in the dependency node's {@link DependencyNode#getData() custom data} under which a reference to the
-     * {@link DependencyNode} which has won the conflict is stored.
-     */
-    public static final String NODE_DATA_WINNER = "conflict.winner";
-
-    /**
-     * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the scope of the
-     * dependency before scope derivation and conflict resolution is stored.
-     */
-    public static final String NODE_DATA_ORIGINAL_SCOPE = "conflict.originalScope";
-
-    /**
-     * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the optional flag of
-     * the dependency before derivation and conflict resolution is stored.
-     */
-    public static final String NODE_DATA_ORIGINAL_OPTIONALITY = "conflict.originalOptionality";
-
-    private final VersionSelector versionSelector;
-
-    private final ScopeSelector scopeSelector;
-
-    private final ScopeDeriver scopeDeriver;
-
-    private final OptionalitySelector optionalitySelector;
-
-    /**
-     * Creates a new conflict resolver instance with the specified hooks.
-     * 
-     * @param versionSelector The version selector to use, must not be {@code null}.
-     * @param scopeSelector The scope selector to use, must not be {@code null}.
-     * @param optionalitySelector The optionality selector ot use, must not be {@code null}.
-     * @param scopeDeriver The scope deriver to use, must not be {@code null}.
-     */
-    public ConflictResolver( VersionSelector versionSelector, ScopeSelector scopeSelector,
-                             OptionalitySelector optionalitySelector, ScopeDeriver scopeDeriver )
-    {
-        if ( versionSelector == null )
-        {
-            throw new IllegalArgumentException( "version selector not specified" );
-        }
-        this.versionSelector = versionSelector;
-        if ( scopeSelector == null )
-        {
-            throw new IllegalArgumentException( "scope selector not specified" );
-        }
-        this.scopeSelector = scopeSelector;
-        if ( scopeDeriver == null )
-        {
-            throw new IllegalArgumentException( "scope deriver not specified" );
-        }
-        this.scopeDeriver = scopeDeriver;
-        if ( optionalitySelector == null )
-        {
-            throw new IllegalArgumentException( "optionality selector not specified" );
-        }
-        this.optionalitySelector = optionalitySelector;
-    }
-
-    public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
-        throws RepositoryException
-    {
-        List<?> sortedConflictIds = (List<?>) context.get( TransformationContextKeys.SORTED_CONFLICT_IDS );
-        if ( sortedConflictIds == null )
-        {
-            ConflictIdSorter sorter = new ConflictIdSorter();
-            sorter.transformGraph( node, context );
-
-            sortedConflictIds = (List<?>) context.get( TransformationContextKeys.SORTED_CONFLICT_IDS );
-        }
-
-//        @SuppressWarnings( "unchecked" )
-//        Map<String, Object> stats = (Map<String, Object>) context.get( TransformationContextKeys.STATS );
-//        long time1 = System.currentTimeMillis();
-
-        @SuppressWarnings( "unchecked" )
-        Collection<Collection<?>> conflictIdCycles =
-            (Collection<Collection<?>>) context.get( TransformationContextKeys.CYCLIC_CONFLICT_IDS );
-        if ( conflictIdCycles == null )
-        {
-            throw new RepositoryException( "conflict id cycles have not been identified" );
-        }
-
-        Map<?, ?> conflictIds = (Map<?, ?>) context.get( TransformationContextKeys.CONFLICT_IDS );
-        if ( conflictIds == null )
-        {
-            throw new RepositoryException( "conflict groups have not been identified" );
-        }
-
-        Map<Object, Collection<Object>> cyclicPredecessors = new HashMap<>();
-        for ( Collection<?> cycle : conflictIdCycles )
-        {
-            for ( Object conflictId : cycle )
-            {
-                Collection<Object> predecessors =
-                        cyclicPredecessors.computeIfAbsent( conflictId, k -> new HashSet<>() );
-                predecessors.addAll( cycle );
-            }
-        }
-
-        State state = new State( node, conflictIds, sortedConflictIds.size(), context );
-        for ( Iterator<?> it = sortedConflictIds.iterator(); it.hasNext(); )
-        {
-            Object conflictId = it.next();
-
-            // reset data structures for next graph walk
-            state.prepare( conflictId, cyclicPredecessors.get( conflictId ) );
-
-            // find nodes with the current conflict id and while walking the graph (more deeply), nuke leftover losers
-            gatherConflictItems( node, state );
-
-            // now that we know the min depth of the parents, update depth of conflict items
-            state.finish();
-
-            // earlier runs might have nuked all parents of the current conflict id, so it might not exist anymore
-            if ( !state.items.isEmpty() )
-            {
-                ConflictContext ctx = state.conflictCtx;
-                state.versionSelector.selectVersion( ctx );
-                if ( ctx.winner == null )
-                {
-                    throw new RepositoryException( "conflict resolver did not select winner among " + state.items );
-                }
-                DependencyNode winner = ctx.winner.node;
-
-                state.scopeSelector.selectScope( ctx );
-                if ( state.verbose )
-                {
-                    winner.setData( NODE_DATA_ORIGINAL_SCOPE, winner.getDependency().getScope() );
-                }
-                winner.setScope( ctx.scope );
-
-                state.optionalitySelector.selectOptionality( ctx );
-                if ( state.verbose )
-                {
-                    winner.setData( NODE_DATA_ORIGINAL_OPTIONALITY, winner.getDependency().isOptional() );
-                }
-                winner.getDependency().setOptional( ctx.optional );
-//                winner.setOptional( ctx.optional );
-
-                removeLosers( state );
-            }
-
-            // record the winner so we can detect leftover losers during future graph walks
-            state.winner();
-
-            // in case of cycles, trigger final graph walk to ensure all leftover losers are gone
-            if ( !it.hasNext() && !conflictIdCycles.isEmpty() && state.conflictCtx.winner != null )
-            {
-                DependencyNode winner = state.conflictCtx.winner.node;
-                state.prepare( state, null );
-                gatherConflictItems( winner, state );
-            }
-        }
-
-//        if ( stats != null )
-//        {
-//            long time2 = System.currentTimeMillis();
-//            stats.put( "ConflictResolver.totalTime", time2 - time1 );
-//            stats.put( "ConflictResolver.conflictItemCount", state.totalConflictItems );
-//        }
-
-        return node;
-    }
-
-    private boolean gatherConflictItems( DependencyNode node, State state )
-        throws RepositoryException
-    {
-        Object conflictId = state.conflictIds.get( node );
-        if ( state.currentId.equals( conflictId ) )
-        {
-            // found it, add conflict item (if not already done earlier by another path)
-            state.add( node );
-            // we don't recurse here so we might miss losers beneath us, those will be nuked during future walks below
-        }
-        else if ( state.loser( node, conflictId ) )
-        {
-            // found a leftover loser (likely in a cycle) of an already processed conflict id, tell caller to nuke it
-            return false;
-        }
-        else if ( state.push( node, conflictId ) )
-        {
-            // found potential parent, no cycle and not visisted before with the same derived scope, so recurse
-            for ( Iterator<DependencyNode> it = node.getChildren().iterator(); it.hasNext(); )
-            {
-                DependencyNode child = it.next();
-                if ( !gatherConflictItems( child, state ) )
-                {
-                    it.remove();
-                }
-            }
-            state.pop();
-        }
-        return true;
-    }
-
-    private void removeLosers( State state )
-    {
-        ConflictItem winner = state.conflictCtx.winner;
-        List<DependencyNode> previousParent = null;
-        ListIterator<DependencyNode> childIt = null;
-        boolean conflictVisualized = false;
-        for ( ConflictItem item : state.items )
-        {
-            if ( item == winner )
-            {
-                continue;
-            }
-            if ( item.parent != previousParent )
-            {
-                childIt = item.parent.listIterator();
-                previousParent = item.parent;
-                conflictVisualized = false;
-            }
-            while ( childIt.hasNext() )
-            {
-                DependencyNode child = childIt.next();
-                if ( child == item.node )
-                {
-                    if ( state.verbose && !conflictVisualized && item.parent != winner.parent )
-                    {
-                        conflictVisualized = true;
-                        DependencyNode loser = new DefaultDependencyNode( child );
-                        loser.setData( NODE_DATA_WINNER, winner.node );
-                        loser.setData( NODE_DATA_ORIGINAL_SCOPE, loser.getDependency().getScope() );
-                        loser.setData( NODE_DATA_ORIGINAL_OPTIONALITY, loser.getDependency().isOptional() );
-                        loser.setScope( item.getScopes().iterator().next() );
-//                        loser.setChildren( Collections.<DependencyNode>emptyList() );
-                        childIt.set( loser );
-                    }
-                    else
-                    {
-                        childIt.remove();
-                    }
-                    break;
-                }
-            }
-        }
-        // there might still be losers beneath the winner (e.g. in case of cycles)
-        // those will be nuked during future graph walks when we include the winner in the recursion
-    }
-
-    static final class NodeInfo
-    {
-
-        /**
-         * The smallest depth at which the node was seen, used for "the" depth of its conflict items.
-         */
-        int minDepth;
-
-        /**
-         * The set of derived scopes the node was visited with, used to check whether an already seen node needs to be
-         * revisited again in context of another scope. To conserve memory, we start with {@code String} and update to
-         * {@code Set<String>} if needed.
-         */
-        Object derivedScopes;
-
-        /**
-         * The set of derived optionalities the node was visited with, used to check whether an already seen node needs
-         * to be revisited again in context of another optionality. To conserve memory, encoded as bit field (bit 0 ->
-         * optional=false, bit 1 -> optional=true).
-         */
-        int derivedOptionalities;
-
-        /**
-         * The conflict items which are immediate children of the node, used to easily update those conflict items after
-         * a new parent scope/optionality was encountered.
-         */
-        List<ConflictItem> children;
-
-        static final int CHANGE_SCOPE = 0x01;
-
-        static final int CHANGE_OPTIONAL = 0x02;
-
-        private static final int OPT_FALSE = 0x01;
-
-        private static final int OPT_TRUE = 0x02;
-
-        NodeInfo( int depth, String derivedScope, boolean optional )
-        {
-            minDepth = depth;
-            derivedScopes = derivedScope;
-            derivedOptionalities = optional ? OPT_TRUE : OPT_FALSE;
-        }
-
-        @SuppressWarnings( "unchecked" )
-        int update( int depth, String derivedScope, boolean optional )
-        {
-            if ( depth < minDepth )
-            {
-                minDepth = depth;
-            }
-            int changes;
-            if ( derivedScopes.equals( derivedScope ) )
-            {
-                changes = 0;
-            }
-            else if ( derivedScopes instanceof Collection )
-            {
-                changes = ( (Collection<String>) derivedScopes ).add( derivedScope ) ? CHANGE_SCOPE : 0;
-            }
-            else
-            {
-                Collection<String> scopes = new HashSet<>();
-                scopes.add( (String) derivedScopes );
-                scopes.add( derivedScope );
-                derivedScopes = scopes;
-                changes = CHANGE_SCOPE;
-            }
-            int bit = optional ? OPT_TRUE : OPT_FALSE;
-            if ( ( derivedOptionalities & bit ) == 0 )
-            {
-                derivedOptionalities |= bit;
-                changes |= CHANGE_OPTIONAL;
-            }
-            return changes;
-        }
-
-        void add( ConflictItem item )
-        {
-            if ( children == null )
-            {
-                children = new ArrayList<>( 1 );
-            }
-            children.add( item );
-        }
-
-    }
-
-    final class State
-    {
-
-        /**
-         * The conflict id currently processed.
-         */
-        Object currentId;
-
-        /**
-         * Stats counter.
-         */
-        int totalConflictItems;
-
-        /**
-         * Flag whether we should keep losers in the graph to enable visualization/troubleshooting of conflicts.
-         */
-        final boolean verbose;
-
-        /**
-         * A mapping from conflict id to winner node, helps to recognize nodes that have their effective
-         * scope&optionality set or are leftovers from previous removals.
-         */
-        final Map<Object, DependencyNode> resolvedIds;
-
-        /**
-         * The set of conflict ids which could apply to ancestors of nodes with the current conflict id, used to avoid
-         * recursion early on. This is basically a superset of the key set of resolvedIds, the additional ids account
-         * for cyclic dependencies.
-         */
-        final Collection<Object> potentialAncestorIds;
-
-        /**
-         * The output from the conflict marker
-         */
-        final Map<?, ?> conflictIds;
-
-        /**
-         * The conflict items we have gathered so far for the current conflict id.
-         */
-        final List<ConflictItem> items;
-
-        /**
-         * The (conceptual) mapping from nodes to extra infos, technically keyed by the node's child list which better
-         * captures the identity of a node since we're basically concerned with effects towards children.
-         */
-        final Map<List<DependencyNode>, NodeInfo> infos;
-
-        /**
-         * The set of nodes on the DFS stack to detect cycles, technically keyed by the node's child list to match the
-         * dirty graph structure produced by the dependency collector for cycles.
-         */
-        final Map<List<DependencyNode>, Object> stack;
-
-        /**
-         * The stack of parent nodes.
-         */
-        final List<DependencyNode> parentNodes;
-
-        /**
-         * The stack of derived scopes for parent nodes.
-         */
-        final List<String> parentScopes;
-
-        /**
-         * The stack of derived optional flags for parent nodes.
-         */
-        final List<Boolean> parentOptionals;
-
-        /**
-         * The stack of node infos for parent nodes, may contain {@code null} which is used to disable creating new
-         * conflict items when visiting their parent again (conflict items are meant to be unique by parent-node combo).
-         */
-        final List<NodeInfo> parentInfos;
-
-        /**
-         * The conflict context passed to the version/scope/optionality selectors, updated as we move along rather than
-         * recreated to avoid tmp objects.
-         */
-        final ConflictContext conflictCtx;
-
-        /**
-         * The scope context passed to the scope deriver, updated as we move along rather than recreated to avoid tmp
-         * objects.
-         */
-        final ScopeContext scopeCtx;
-
-        /**
-         * The effective version selector, i.e. after initialization.
-         */
-        final VersionSelector versionSelector;
-
-        /**
-         * The effective scope selector, i.e. after initialization.
-         */
-        final ScopeSelector scopeSelector;
-
-        /**
-         * The effective scope deriver, i.e. after initialization.
-         */
-        final ScopeDeriver scopeDeriver;
-
-        /**
-         * The effective optionality selector, i.e. after initialization.
-         */
-        final OptionalitySelector optionalitySelector;
-
-        State( DependencyNode root, Map<?, ?> conflictIds, int conflictIdCount,
-               DependencyGraphTransformationContext context )
-            throws RepositoryException
-        {
-            this.conflictIds = conflictIds;
-            verbose = ConfigUtils.getBoolean( context.getSession(), false, CONFIG_PROP_VERBOSE );
-            potentialAncestorIds = new HashSet<>( conflictIdCount * 2 );
-            resolvedIds = new HashMap<>( conflictIdCount * 2 );
-            items = new ArrayList<>( 256 );
-            infos = new IdentityHashMap<>( 64 );
-            stack = new IdentityHashMap<>( 64 );
-            parentNodes = new ArrayList<>( 64 );
-            parentScopes = new ArrayList<>( 64 );
-            parentOptionals = new ArrayList<>( 64 );
-            parentInfos = new ArrayList<>( 64 );
-            conflictCtx = new ConflictContext( root, conflictIds, items );
-            scopeCtx = new ScopeContext( null, null );
-            versionSelector = ConflictResolver.this.versionSelector.getInstance( root, context );
-            scopeSelector = ConflictResolver.this.scopeSelector.getInstance( root, context );
-            scopeDeriver = ConflictResolver.this.scopeDeriver.getInstance( root, context );
-            optionalitySelector = ConflictResolver.this.optionalitySelector.getInstance( root, context );
-        }
-
-        void prepare( Object conflictId, Collection<Object> cyclicPredecessors )
-        {
-            currentId = conflictId;
-            conflictCtx.conflictId = conflictId;
-            conflictCtx.winner = null;
-            conflictCtx.scope = null;
-            conflictCtx.optional = null;
-            items.clear();
-            infos.clear();
-            if ( cyclicPredecessors != null )
-            {
-                potentialAncestorIds.addAll( cyclicPredecessors );
-            }
-        }
-
-        void finish()
-        {
-            List<DependencyNode> previousParent = null;
-            int previousDepth = 0;
-            totalConflictItems += items.size();
-            for ( int i = items.size() - 1; i >= 0; i-- )
-            {
-                ConflictItem item = items.get( i );
-                if ( item.parent == previousParent )
-                {
-                    item.depth = previousDepth;
-                }
-                else if ( item.parent != null )
-                {
-                    previousParent = item.parent;
-                    NodeInfo info = infos.get( previousParent );
-                    previousDepth = info.minDepth + 1;
-                    item.depth = previousDepth;
-                }
-            }
-            potentialAncestorIds.add( currentId );
-        }
-
-        void winner()
-        {
-            resolvedIds.put( currentId, ( conflictCtx.winner != null ) ? conflictCtx.winner.node : null );
-        }
-
-        boolean loser( DependencyNode node, Object conflictId )
-        {
-            DependencyNode winner = resolvedIds.get( conflictId );
-            return winner != null && winner != node;
-        }
-
-        boolean push( DependencyNode node, Object conflictId )
-            throws RepositoryException
-        {
-            if ( conflictId == null )
-            {
-                if ( node.getDependency() != null )
-                {
-                    if ( node.getData().get( NODE_DATA_WINNER ) != null )
-                    {
-                        return false;
-                    }
-                    throw new RepositoryException( "missing conflict id for node " + node );
-                }
-            }
-            else if ( !potentialAncestorIds.contains( conflictId ) )
-            {
-                return false;
-            }
-
-            List<DependencyNode> graphNode = node.getChildren();
-            if ( stack.put( graphNode, Boolean.TRUE ) != null )
-            {
-                return false;
-            }
-
-            int depth = depth();
-            String scope = deriveScope( node, conflictId );
-            boolean optional = deriveOptional( node, conflictId );
-            NodeInfo info = infos.get( graphNode );
-            if ( info == null )
-            {
-                info = new NodeInfo( depth, scope, optional );
-                infos.put( graphNode, info );
-                parentInfos.add( info );
-                parentNodes.add( node );
-                parentScopes.add( scope );
-                parentOptionals.add( optional );
-            }
-            else
-            {
-                int changes = info.update( depth, scope, optional );
-                if ( changes == 0 )
-                {
-                    stack.remove( graphNode );
-                    return false;
-                }
-                parentInfos.add( null ); // disable creating new conflict items, we update the existing ones below
-                parentNodes.add( node );
-                parentScopes.add( scope );
-                parentOptionals.add( optional );
-                if ( info.children != null )
-                {
-                    if ( ( changes & NodeInfo.CHANGE_SCOPE ) != 0 )
-                    {
-                        for ( int i = info.children.size() - 1; i >= 0; i-- )
-                        {
-                            ConflictItem item = info.children.get( i );
-                            String childScope = deriveScope( item.node, null );
-                            item.addScope( childScope );
-                        }
-                    }
-                    if ( ( changes & NodeInfo.CHANGE_OPTIONAL ) != 0 )
-                    {
-                        for ( int i = info.children.size() - 1; i >= 0; i-- )
-                        {
-                            ConflictItem item = info.children.get( i );
-                            boolean childOptional = deriveOptional( item.node, null );
-                            item.addOptional( childOptional );
-                        }
-                    }
-                }
-            }
-
-            return true;
-        }
-
-        void pop()
-        {
-            int last = parentInfos.size() - 1;
-            parentInfos.remove( last );
-            parentScopes.remove( last );
-            parentOptionals.remove( last );
-            DependencyNode node = parentNodes.remove( last );
-            stack.remove( node.getChildren() );
-        }
-
-        void add( DependencyNode node )
-            throws RepositoryException
-        {
-            DependencyNode parent = parent();
-            if ( parent == null )
-            {
-                ConflictItem item = newConflictItem( parent, node );
-                items.add( item );
-            }
-            else
-            {
-                NodeInfo info = parentInfos.get( parentInfos.size() - 1 );
-                if ( info != null )
-                {
-                    ConflictItem item = newConflictItem( parent, node );
-                    info.add( item );
-                    items.add( item );
-                }
-            }
-        }
-
-        private ConflictItem newConflictItem( DependencyNode parent, DependencyNode node )
-            throws RepositoryException
-        {
-            return new ConflictItem( parent, node, deriveScope( node, null ), deriveOptional( node, null ) );
-        }
-
-        private int depth()
-        {
-            return parentNodes.size();
-        }
-
-        private DependencyNode parent()
-        {
-            int size = parentNodes.size();
-            return ( size <= 0 ) ? null : parentNodes.get( size - 1 );
-        }
-
-        private String deriveScope( DependencyNode node, Object conflictId )
-            throws RepositoryException
-        {
-            if ( node.getPremanagedScope() != null
-                || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
-//            if ( ( node.getManagedBits() & DependencyNode.MANAGED_SCOPE ) != 0
-//                || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
-            {
-                return scope( node.getDependency() );
-            }
-
-            int depth = parentNodes.size();
-            scopes( depth, node.getDependency() );
-            if ( depth > 0 )
-            {
-                scopeDeriver.deriveScope( scopeCtx );
-            }
-            return scopeCtx.derivedScope;
-        }
-
-        private void scopes( int parent, Dependency child )
-        {
-            scopeCtx.parentScope = ( parent > 0 ) ? parentScopes.get( parent - 1 ) : null;
-            scopeCtx.derivedScope = scope( child );
-            scopeCtx.childScope = scopeCtx.derivedScope;
-        }
-
-        private String scope( Dependency dependency )
-        {
-            return ( dependency != null ) ? dependency.getScope() : null;
-        }
-
-        private boolean deriveOptional( DependencyNode node, Object conflictId )
-        {
-            Dependency dep = node.getDependency();
-            boolean optional = dep != null && dep.isOptional();
-            if ( optional
-                || ( node.getData().get( NODE_DATA_ORIGINAL_OPTIONALITY ) != null
-                    && (Boolean) node.getData().get( NODE_DATA_ORIGINAL_OPTIONALITY ) )
-                || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
-//            if ( optional || ( node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL ) != 0
-//                || ( conflictId != null && resolvedIds.containsKey( conflictId ) ) )
-            {
-                return optional;
-            }
-            int depth = parentNodes.size();
-            return ( depth > 0 ) ? parentOptionals.get( depth - 1 ) : false;
-        }
-
-    }
-
-    /**
-     * A context used to hold information that is relevant for deriving the scope of a child dependency.
-     * 
-     * @see ScopeDeriver
-     * This class is not intended to be instantiated by clients in production code, the constructor may
-     *                change without notice and only exists to enable unit testing.
-     */
-    public static final class ScopeContext
-    {
-
-        String parentScope;
-
-        String childScope;
-
-        String derivedScope;
-
-        /**
-         * Creates a new scope context with the specified properties.
-         * 
-         * @param parentScope The scope of the parent dependency, may be {@code null}.
-         * @param childScope The scope of the child dependency, may be {@code null}.
-         * This class is not intended to be instantiated by clients in production code, the constructor may
-         *              change without notice and only exists to enable unit testing.
-         */
-        public ScopeContext( String parentScope, String childScope )
-        {
-            this.parentScope = ( parentScope != null ) ? parentScope : "";
-            derivedScope = ( childScope != null ) ? childScope : "";
-            this.childScope = derivedScope;
-        }
-
-        /**
-         * Gets the scope of the parent dependency. This is usually the scope that was derived by earlier invocations of
-         * the scope deriver.
-         * 
-         * @return The scope of the parent dependency, never {@code null}.
-         */
-        public String getParentScope()
-        {
-            return parentScope;
-        }
-
-        /**
-         * Gets the original scope of the child dependency. This is the scope that was declared in the artifact
-         * descriptor of the parent dependency.
-         * 
-         * @return The original scope of the child dependency, never {@code null}.
-         */
-        public String getChildScope()
-        {
-            return childScope;
-        }
-
-        /**
-         * Gets the derived scope of the child dependency. This is initially equal to {@link #getChildScope()} until the
-         * scope deriver makes changes.
-         * 
-         * @return The derived scope of the child dependency, never {@code null}.
-         */
-        public String getDerivedScope()
-        {
-            return derivedScope;
-        }
-
-        /**
-         * Sets the derived scope of the child dependency.
-         * 
-         * @param derivedScope The derived scope of the dependency, may be {@code null}.
-         */
-        public void setDerivedScope( String derivedScope )
-        {
-            this.derivedScope = ( derivedScope != null ) ? derivedScope : "";
-        }
-
-    }
-
-    /**
-     * A conflicting dependency.
-     * 
-     * This class is not intended to be instantiated by clients in production code, the constructor may
-     *                change without notice and only exists to enable unit testing.
-     */
-    public static final class ConflictItem
-    {
-
-        // nodes can share child lists, we care about the unique owner of a child node which is the child list
-        final List<DependencyNode> parent;
-
-        // only for debugging/toString() to help identify the parent node(s)
-        final Artifact artifact;
-
-        final DependencyNode node;
-
-        int depth;
-
-        // we start with String and update to Set<String> if needed
-        Object scopes;
-
-        // bit field of OPTIONAL_FALSE and OPTIONAL_TRUE
-        int optionalities;
-
-        /**
-         * Bit flag indicating whether one or more paths consider the dependency non-optional.
-         */
-        public static final int OPTIONAL_FALSE = 0x01;
-
-        /**
-         * Bit flag indicating whether one or more paths consider the dependency optional.
-         */
-        public static final int OPTIONAL_TRUE = 0x02;
-
-        ConflictItem( DependencyNode parent, DependencyNode node, String scope, boolean optional )
-        {
-            if ( parent != null )
-            {
-                this.parent = parent.getChildren();
-                this.artifact = parent.getDependency().getArtifact();
-//                this.artifact = parent.getArtifact();
-            }
-            else
-            {
-                this.parent = null;
-                this.artifact = null;
-            }
-            this.node = node;
-            this.scopes = scope;
-            this.optionalities = optional ? OPTIONAL_TRUE : OPTIONAL_FALSE;
-        }
-
-        /**
-         * Creates a new conflict item with the specified properties.
-         * 
-         * @param parent The parent node of the conflicting dependency, may be {@code null}.
-         * @param node The conflicting dependency, must not be {@code null}.
-         * @param depth The zero-based depth of the conflicting dependency.
-         * @param optionalities The optionalities the dependency was encountered with, encoded as a bit field consisting
-         *            of {@link ConflictResolver.ConflictItem#OPTIONAL_TRUE} and
-         *            {@link ConflictResolver.ConflictItem#OPTIONAL_FALSE}.
-         * @param scopes The derived scopes of the conflicting dependency, must not be {@code null}.
-         * This class is not intended to be instantiated by clients in production code, the constructor may
-         *              change without notice and only exists to enable unit testing.
-         */
-        public ConflictItem( DependencyNode parent, DependencyNode node, int depth, int optionalities,
-                             String... scopes )
-        {
-            this.parent = ( parent != null ) ? parent.getChildren() : null;
-            this.artifact = ( parent != null ) ? parent.getDependency().getArtifact() : null;
-//            this.artifact = ( parent != null ) ? parent.getArtifact() : null;
-            this.node = node;
-            this.depth = depth;
-            this.optionalities = optionalities;
-            this.scopes = Arrays.asList( scopes );
-        }
-
-        /**
-         * Determines whether the specified conflict item is a sibling of this item.
-         * 
-         * @param item The other conflict item, must not be {@code null}.
-         * @return {@code true} if the given item has the same parent as this item, {@code false} otherwise.
-         */
-        public boolean isSibling( ConflictItem item )
-        {
-            return parent == item.parent;
-        }
-
-        /**
-         * Gets the dependency node involved in the conflict.
-         * 
-         * @return The involved dependency node, never {@code null}.
-         */
-        public DependencyNode getNode()
-        {
-            return node;
-        }
-
-        /**
-         * Gets the dependency involved in the conflict, short for {@code getNode.getDependency()}.
-         * 
-         * @return The involved dependency, never {@code null}.
-         */
-        public Dependency getDependency()
-        {
-            return node.getDependency();
-        }
-
-        /**
-         * Gets the zero-based depth at which the conflicting node occurs in the graph. As such, the depth denotes the
-         * number of parent nodes. If actually multiple paths lead to the node, the return value denotes the smallest
-         * possible depth.
-         * 
-         * @return The zero-based depth of the node in the graph.
-         */
-        public int getDepth()
-        {
-            return depth;
-        }
-
-        /**
-         * Gets the derived scopes of the dependency. In general, the same dependency node could be reached via
-         * different paths and each path might result in a different derived scope.
-         * 
-         * @see ScopeDeriver
-         * @return The (read-only) set of derived scopes of the dependency, never {@code null}.
-         */
-        @SuppressWarnings( "unchecked" )
-        public Collection<String> getScopes()
-        {
-            if ( scopes instanceof String )
-            {
-                return Collections.singleton( (String) scopes );
-            }
-            return (Collection<String>) scopes;
-        }
-
-        @SuppressWarnings( "unchecked" )
-        void addScope( String scope )
-        {
-            if ( scopes instanceof Collection )
-            {
-                ( (Collection<String>) scopes ).add( scope );
-            }
-            else if ( !scopes.equals( scope ) )
-            {
-                Collection<Object> set = new HashSet<>();
-                set.add( scopes );
-                set.add( scope );
-                scopes = set;
-            }
-        }
-
-        /**
-         * Gets the derived optionalities of the dependency. In general, the same dependency node could be reached via
-         * different paths and each path might result in a different derived optionality.
-         * 
-         * @return A bit field consisting of {@link ConflictResolver.ConflictItem#OPTIONAL_FALSE} and/or
-         *         {@link ConflictResolver.ConflictItem#OPTIONAL_TRUE} indicating the derived optionalities the
-         *         dependency was encountered with.
-         */
-        public int getOptionalities()
-        {
-            return optionalities;
-        }
-
-        void addOptional( boolean optional )
-        {
-            optionalities |= optional ? OPTIONAL_TRUE : OPTIONAL_FALSE;
-        }
-
-        @Override
-        public String toString()
-        {
-            return node + " @ " + depth + " < " + artifact;
-        }
-
-    }
-
-    /**
-     * A context used to hold information that is relevant for resolving version and scope conflicts.
-     * 
-     * @see VersionSelector
-     * @see ScopeSelector
-     * This class is not intended to be instantiated by clients in production code, the constructor may
-     *                change without notice and only exists to enable unit testing.
-     */
-    public static final class ConflictContext
-    {
-
-        final DependencyNode root;
-
-        final Map<?, ?> conflictIds;
-
-        final Collection<ConflictItem> items;
-
-        Object conflictId;
-
-        ConflictItem winner;
-
-        String scope;
-
-        Boolean optional;
-
-        ConflictContext( DependencyNode root, Map<?, ?> conflictIds, Collection<ConflictItem> items )
-        {
-            this.root = root;
-            this.conflictIds = conflictIds;
-            this.items = Collections.unmodifiableCollection( items );
-        }
-
-        /**
-         * Creates a new conflict context.
-         * 
-         * @param root The root node of the dependency graph, must not be {@code null}.
-         * @param conflictId The conflict id for the set of conflicting dependencies in this context, must not be
-         *            {@code null}.
-         * @param conflictIds The mapping from dependency node to conflict id, must not be {@code null}.
-         * @param items The conflict items in this context, must not be {@code null}.
-         * This class is not intended to be instantiated by clients in production code, the constructor may
-         *              change without notice and only exists to enable unit testing.
-         */
-        public ConflictContext( DependencyNode root, Object conflictId, Map<DependencyNode, Object> conflictIds,
-                                Collection<ConflictItem> items )
-        {
-            this( root, conflictIds, items );
-            this.conflictId = conflictId;
-        }
-
-        /**
-         * Gets the root node of the dependency graph being transformed.
-         * 
-         * @return The root node of the dependeny graph, never {@code null}.
-         */
-        public DependencyNode getRoot()
-        {
-            return root;
-        }
-
-        /**
-         * Determines whether the specified dependency node belongs to this conflict context.
-         * 
-         * @param node The dependency node to check, must not be {@code null}.
-         * @return {@code true} if the given node belongs to this conflict context, {@code false} otherwise.
-         */
-        public boolean isIncluded( DependencyNode node )
-        {
-            return conflictId.equals( conflictIds.get( node ) );
-        }
-
-        /**
-         * Gets the collection of conflict items in this context.
-         * 
-         * @return The (read-only) collection of conflict items in this context, never {@code null}.
-         */
-        public Collection<ConflictItem> getItems()
-        {
-            return items;
-        }
-
-        /**
-         * Gets the conflict item which has been selected as the winner among the conflicting dependencies.
-         * 
-         * @return The winning conflict item or {@code null} if not set yet.
-         */
-        public ConflictItem getWinner()
-        {
-            return winner;
-        }
-
-        /**
-         * Sets the conflict item which has been selected as the winner among the conflicting dependencies.
-         * 
-         * @param winner The winning conflict item, may be {@code null}.
-         */
-        public void setWinner( ConflictItem winner )
-        {
-            this.winner = winner;
-        }
-
-        /**
-         * Gets the effective scope of the winning dependency.
-         * 
-         * @return The effective scope of the winning dependency or {@code null} if none.
-         */
-        public String getScope()
-        {
-            return scope;
-        }
-
-        /**
-         * Sets the effective scope of the winning dependency.
-         * 
-         * @param scope The effective scope, may be {@code null}.
-         */
-        public void setScope( String scope )
-        {
-            this.scope = scope;
-        }
-
-        /**
-         * Gets the effective optional flag of the winning dependency.
-         * 
-         * @return The effective optional flag or {@code null} if none.
-         */
-        public Boolean getOptional()
-        {
-            return optional;
-        }
-
-        /**
-         * Sets the effective optional flag of the winning dependency.
-         * 
-         * @param optional The effective optional flag, may be {@code null}.
-         */
-        public void setOptional( Boolean optional )
-        {
-            this.optional = optional;
-        }
-
-        @Override
-        public String toString()
-        {
-            return winner + " @ " + scope + " < " + items;
-        }
-
-    }
-
-    /**
-     * An extension point of {@link ConflictResolver} that determines the winner among conflicting dependencies. The
-     * winning node (and its children) will be retained in the dependency graph, the other nodes will get removed. The
-     * version selector does not need to deal with potential scope conflicts, these will be addressed afterwards by the
-     * {@link ScopeSelector}. Implementations must be stateless.
-     */
-    public abstract static class VersionSelector
-    {
-
-        /**
-         * Retrieves the version selector for use during the specified graph transformation. The conflict resolver calls
-         * this method once per
-         * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
-         * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
-         * implementations need to be stateless, a new instance needs to be returned to hold such auxiliary data. The
-         * default implementation simply returns the current instance which is appropriate for implementations which do
-         * not require auxiliary data.
-         * 
-         * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
-         * @param context The graph transformation context, must not be {@code null}.
-         * @return The scope deriver to use for the given graph transformation, never {@code null}.
-         * @throws RepositoryException If the instance could not be retrieved.
-         */
-        public VersionSelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
-            throws RepositoryException
-        {
-            return this;
-        }
-
-        /**
-         * Determines the winning node among conflicting dependencies. Implementations will usually iterate
-         * {@link ConflictContext#getItems()}, inspect {@link ConflictItem#getNode()} and eventually call
-         * {@link ConflictContext#setWinner(ConflictResolver.ConflictItem)} to deliver the winner. Failure to select a
-         * winner will automatically fail the entire conflict resolution.
-         * 
-         * @param context The conflict context, must not be {@code null}.
-         * @throws RepositoryException If the version selection failed.
-         */
-        public abstract void selectVersion( ConflictContext context )
-            throws RepositoryException;
-
-    }
-
-    /**
-     * An extension point of {@link ConflictResolver} that determines the effective scope of a dependency from a
-     * potentially conflicting set of {@link ScopeDeriver derived scopes}. The scope selector gets invoked after the
-     * {@link VersionSelector} has picked the winning node. Implementations must be stateless.
-     */
-    public abstract static class ScopeSelector
-    {
-
-        /**
-         * Retrieves the scope selector for use during the specified graph transformation. The conflict resolver calls
-         * this method once per
-         * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
-         * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
-         * implementations need to be stateless, a new instance needs to be returned to hold such auxiliary data. The
-         * default implementation simply returns the current instance which is appropriate for implementations which do
-         * not require auxiliary data.
-         * 
-         * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
-         * @param context The graph transformation context, must not be {@code null}.
-         * @return The scope selector to use for the given graph transformation, never {@code null}.
-         * @throws RepositoryException If the instance could not be retrieved.
-         */
-        public ScopeSelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
-            throws RepositoryException
-        {
-            return this;
-        }
-
-        /**
-         * Determines the effective scope of the dependency given by {@link ConflictContext#getWinner()}.
-         * Implementations will usually iterate {@link ConflictContext#getItems()}, inspect
-         * {@link ConflictItem#getScopes()} and eventually call {@link ConflictContext#setScope(String)} to deliver the
-         * effective scope.
-         * 
-         * @param context The conflict context, must not be {@code null}.
-         * @throws RepositoryException If the scope selection failed.
-         */
-        public abstract void selectScope( ConflictContext context )
-            throws RepositoryException;
-
-    }
-
-    /**
-     * An extension point of {@link ConflictResolver} that determines the scope of a dependency in relation to the scope
-     * of its parent. Implementations must be stateless.
-     */
-    public abstract static class ScopeDeriver
-    {
-
-        /**
-         * Retrieves the scope deriver for use during the specified graph transformation. The conflict resolver calls
-         * this method once per
-         * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
-         * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
-         * implementations need to be stateless, a new instance needs to be returned to hold such auxiliary data. The
-         * default implementation simply returns the current instance which is appropriate for implementations which do
-         * not require auxiliary data.
-         * 
-         * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
-         * @param context The graph transformation context, must not be {@code null}.
-         * @return The scope deriver to use for the given graph transformation, never {@code null}.
-         * @throws RepositoryException If the instance could not be retrieved.
-         */
-        public ScopeDeriver getInstance( DependencyNode root, DependencyGraphTransformationContext context )
-            throws RepositoryException
-        {
-            return this;
-        }
-
-        /**
-         * Determines the scope of a dependency in relation to the scope of its parent. Implementors need to call
-         * {@link ScopeContext#setDerivedScope(String)} to deliver the result of their calculation. If said method is
-         * not invoked, the conflict resolver will assume the scope of the child dependency remains unchanged.
-         * 
-         * @param context The scope context, must not be {@code null}.
-         * @throws RepositoryException If the scope deriviation failed.
-         */
-        public abstract void deriveScope( ScopeContext context )
-            throws RepositoryException;
-
-    }
-
-    /**
-     * An extension point of {@link ConflictResolver} that determines the effective optional flag of a dependency from a
-     * potentially conflicting set of derived optionalities. The optionality selector gets invoked after the
-     * {@link VersionSelector} has picked the winning node. Implementations must be stateless.
-     */
-    public abstract static class OptionalitySelector
-    {
-
-        /**
-         * Retrieves the optionality selector for use during the specified graph transformation. The conflict resolver
-         * calls this method once per
-         * {@link ConflictResolver#transformGraph(DependencyNode, DependencyGraphTransformationContext)} invocation to
-         * allow implementations to prepare any auxiliary data that is needed for their operation. Given that
-         * implementations need to be stateless, a new instance needs to be returned to hold such auxiliary data. The
-         * default implementation simply returns the current instance which is appropriate for implementations which do
-         * not require auxiliary data.
-         * 
-         * @param root The root node of the (possibly cyclic!) graph to transform, must not be {@code null}.
-         * @param context The graph transformation context, must not be {@code null}.
-         * @return The optionality selector to use for the given graph transformation, never {@code null}.
-         * @throws RepositoryException If the instance could not be retrieved.
-         */
-        public OptionalitySelector getInstance( DependencyNode root, DependencyGraphTransformationContext context )
-            throws RepositoryException
-        {
-            return this;
-        }
-
-        /**
-         * Determines the effective optional flag of the dependency given by {@link ConflictContext#getWinner()}.
-         * Implementations will usually iterate {@link ConflictContext#getItems()}, inspect
-         * {@link ConflictItem#getOptionalities()} and eventually call {@link ConflictContext#setOptional(Boolean)} to
-         * deliver the effective optional flag.
-         * 
-         * @param context The conflict context, must not be {@code null}.
-         * @throws RepositoryException If the optionality selection failed.
-         */
-        public abstract void selectOptionality( ConflictContext context )
-            throws RepositoryException;
-
-    }
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ExclusionDependencySelector.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ExclusionDependencySelector.java
deleted file mode 100644
index 2808595..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/ExclusionDependencySelector.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.TreeSet;
-
-import org.sonatype.aether.artifact.Artifact;
-import org.sonatype.aether.collection.DependencyCollectionContext;
-import org.sonatype.aether.collection.DependencySelector;
-import org.sonatype.aether.graph.Dependency;
-import org.sonatype.aether.graph.Exclusion;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public class ExclusionDependencySelector
-    implements DependencySelector
-{
-
-    // sorted and dupe-free array, faster to iterate than LinkedHashSet
-    private final Exclusion[] exclusions;
-
-    private int hashCode;
-
-    /**
-     * Creates a new selector without any exclusions.
-     */
-    public ExclusionDependencySelector()
-    {
-        this.exclusions = new Exclusion[0];
-    }
-
-    /**
-     * Creates a new selector with the specified exclusions.
-     * 
-     * @param exclusions The exclusions, may be {@code null}.
-     */
-    public ExclusionDependencySelector( Collection<Exclusion> exclusions )
-    {
-        if ( exclusions != null && !exclusions.isEmpty() )
-        {
-            TreeSet<Exclusion> sorted = new TreeSet<>( ExclusionComparator.INSTANCE );
-            sorted.addAll( exclusions );
-            this.exclusions = sorted.toArray( new Exclusion[0] );
-        }
-        else
-        {
-            this.exclusions = new Exclusion[0];
-        }
-    }
-
-    private ExclusionDependencySelector( Exclusion[] exclusions )
-    {
-        this.exclusions = exclusions;
-    }
-
-    public boolean selectDependency( Dependency dependency )
-    {
-        Artifact artifact = dependency.getArtifact();
-        for ( Exclusion exclusion : exclusions )
-        {
-            if ( matches( exclusion, artifact ) )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private boolean matches( Exclusion exclusion, Artifact artifact )
-    {
-        if ( !matches( exclusion.getArtifactId(), artifact.getArtifactId() ) )
-        {
-            return false;
-        }
-        if ( !matches( exclusion.getGroupId(), artifact.getGroupId() ) )
-        {
-            return false;
-        }
-        if ( !matches( exclusion.getExtension(), artifact.getExtension() ) )
-        {
-            return false;
-        }
-        if ( !matches( exclusion.getClassifier(), artifact.getClassifier() ) )
-        {
-            return false;
-        }
-        return true;
-    }
-
-    private boolean matches( String pattern, String value )
-    {
-        return "*".equals( pattern ) || pattern.equals( value );
-    }
-
-    public DependencySelector deriveChildSelector( DependencyCollectionContext context )
-    {
-        Dependency dependency = context.getDependency();
-        Collection<Exclusion> exclusions = ( dependency != null ) ? dependency.getExclusions() : null;
-        if ( exclusions == null || exclusions.isEmpty() )
-        {
-            return this;
-        }
-
-        Exclusion[] merged = this.exclusions;
-        int count = merged.length;
-        for ( Exclusion exclusion : exclusions )
-        {
-            int index = Arrays.binarySearch( merged, exclusion, ExclusionComparator.INSTANCE );
-            if ( index < 0 )
-            {
-                index = -( index + 1 );
-                if ( count >= merged.length )
-                {
-                    Exclusion[] tmp = new Exclusion[merged.length + exclusions.size()];
-                    System.arraycopy( merged, 0, tmp, 0, index );
-                    tmp[index] = exclusion;
-                    System.arraycopy( merged, index, tmp, index + 1, count - index );
-                    merged = tmp;
-                }
-                else
-                {
-                    System.arraycopy( merged, index, merged, index + 1, count - index );
-                    merged[index] = exclusion;
-                }
-                count++;
-            }
-        }
-        if ( merged == this.exclusions )
-        {
-            return this;
-        }
-        if ( merged.length != count )
-        {
-            Exclusion[] tmp = new Exclusion[count];
-            System.arraycopy( merged, 0, tmp, 0, count );
-            merged = tmp;
-        }
-
-        return new ExclusionDependencySelector( merged );
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        if ( this == obj )
-        {
-            return true;
-        }
-        else if ( null == obj || !getClass().equals( obj.getClass() ) )
-        {
-            return false;
-        }
-
-        ExclusionDependencySelector that = (ExclusionDependencySelector) obj;
-        return Arrays.equals( exclusions, that.exclusions );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        if ( hashCode == 0 )
-        {
-            int hash = getClass().hashCode();
-            hash = hash * 31 + Arrays.hashCode( exclusions );
-            hashCode = hash;
-        }
-        return hashCode;
-    }
-
-    private static class ExclusionComparator
-        implements Comparator<Exclusion>
-    {
-
-        static final ExclusionComparator INSTANCE = new ExclusionComparator();
-
-        public int compare( Exclusion e1, Exclusion e2 )
-        {
-            if ( e1 == null )
-            {
-                return ( e2 == null ) ? 0 : 1;
-            }
-            else if ( e2 == null )
-            {
-                return -1;
-            }
-            int rel = e1.getArtifactId().compareTo( e2.getArtifactId() );
-            if ( rel == 0 )
-            {
-                rel = e1.getGroupId().compareTo( e2.getGroupId() );
-                if ( rel == 0 )
-                {
-                    rel = e1.getExtension().compareTo( e2.getExtension() );
-                    if ( rel == 0 )
-                    {
-                        rel = e1.getClassifier().compareTo( e2.getClassifier() );
-                    }
-                }
-            }
-            return rel;
-        }
-
-    }
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/JavaScopeDeriver.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/JavaScopeDeriver.java
deleted file mode 100644
index d35abf0..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/JavaScopeDeriver.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ScopeContext;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ScopeDeriver;
-import org.sonatype.aether.RepositoryException;
-import org.sonatype.aether.util.artifact.JavaScopes;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public class JavaScopeDeriver
-    extends ScopeDeriver
-{
-
-    @Override
-    public void deriveScope( ScopeContext context )
-        throws RepositoryException
-    {
-        context.setDerivedScope( getDerivedScope( context.getParentScope(), context.getChildScope() ) );
-    }
-
-    private String getDerivedScope( String parentScope, String childScope )
-    {
-        String derivedScope;
-
-        if ( JavaScopes.SYSTEM.equals( childScope ) || JavaScopes.TEST.equals( childScope ) )
-        {
-            derivedScope = childScope;
-        }
-        else if ( parentScope == null || parentScope.length() <= 0 || JavaScopes.COMPILE.equals( parentScope ) )
-        {
-            derivedScope = childScope;
-        }
-        else if ( JavaScopes.TEST.equals( parentScope ) || JavaScopes.RUNTIME.equals( parentScope ) )
-        {
-            derivedScope = parentScope;
-        }
-        else if ( JavaScopes.SYSTEM.equals( parentScope ) || JavaScopes.PROVIDED.equals( parentScope ) )
-        {
-            derivedScope = JavaScopes.PROVIDED;
-        }
-        else
-        {
-            derivedScope = JavaScopes.RUNTIME;
-        }
-
-        return derivedScope;
-    }
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/JavaScopeSelector.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/JavaScopeSelector.java
deleted file mode 100644
index 1950a92..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/JavaScopeSelector.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictContext;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictItem;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ScopeSelector;
-import org.sonatype.aether.RepositoryException;
-import org.sonatype.aether.util.artifact.JavaScopes;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public final class JavaScopeSelector
-    extends ScopeSelector
-{
-
-    @Override
-    public void selectScope( ConflictContext context )
-        throws RepositoryException
-    {
-        String scope = context.getWinner().getDependency().getScope();
-        if ( !JavaScopes.SYSTEM.equals( scope ) )
-        {
-            scope = chooseEffectiveScope( context.getItems() );
-        }
-        context.setScope( scope );
-    }
-
-    private String chooseEffectiveScope( Collection<ConflictItem> items )
-    {
-        Set<String> scopes = new HashSet<>();
-        for ( ConflictItem item : items )
-        {
-            if ( item.getDepth() <= 1 )
-            {
-                return item.getDependency().getScope();
-            }
-            scopes.addAll( item.getScopes() );
-        }
-        return chooseEffectiveScope( scopes );
-    }
-
-    private String chooseEffectiveScope( Set<String> scopes )
-    {
-        if ( scopes.size() > 1 )
-        {
-            scopes.remove( JavaScopes.SYSTEM );
-        }
-
-        String effectiveScope = "";
-
-        if ( scopes.size() == 1 )
-        {
-            effectiveScope = scopes.iterator().next();
-        }
-        else if ( scopes.contains( JavaScopes.COMPILE ) )
-        {
-            effectiveScope = JavaScopes.COMPILE;
-        }
-        else if ( scopes.contains( JavaScopes.RUNTIME ) )
-        {
-            effectiveScope = JavaScopes.RUNTIME;
-        }
-        else if ( scopes.contains( JavaScopes.PROVIDED ) )
-        {
-            effectiveScope = JavaScopes.PROVIDED;
-        }
-        else if ( scopes.contains( JavaScopes.TEST ) )
-        {
-            effectiveScope = JavaScopes.TEST;
-        }
-
-        return effectiveScope;
-    }
-
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/Maven3DirectScopeDependencySelector.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/Maven3DirectScopeDependencySelector.java
deleted file mode 100644
index 9373b90..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/Maven3DirectScopeDependencySelector.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import org.sonatype.aether.collection.DependencyCollectionContext;
-import org.sonatype.aether.collection.DependencySelector;
-import org.sonatype.aether.graph.Dependency;
-
-/**
- * A dependency selector that excludes dependencies of an specific Scope which occur beyond level one of the dependency
- * graph.
- * 
- * @see Dependency#getScope()
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public class Maven3DirectScopeDependencySelector
-    implements DependencySelector
-{
-
-    private final String scope;
-
-    private final int depth;
-
-    public Maven3DirectScopeDependencySelector( String scope )
-    {
-        this( scope, 0 );
-    }
-
-    private Maven3DirectScopeDependencySelector( String scope, int depth )
-    {
-        if ( scope == null )
-        {
-            throw new IllegalArgumentException( "scope is null!" );
-        }
-        this.scope = scope;
-        this.depth = depth;
-    }
-
-    /**
-     * Decides whether the specified dependency should be included in the dependency graph.
-     * 
-     * @param dependency The dependency to check, must not be {@code null}.
-     * @return {@code false} if the dependency should be excluded from the children of the current node, {@code true}
-     *         otherwise.
-     */
-    @Override
-    public boolean selectDependency( Dependency dependency )
-    {
-        return depth < 2 || !scope.equals( dependency.getScope() );
-    }
-
-    /**
-     * Derives a dependency selector for the specified collection context. When calculating the child selector,
-     * implementors are strongly advised to simply return the current instance if nothing changed to help save memory.
-     * 
-     * @param context The dependency collection context, must not be {@code null}.
-     * @return The dependency selector for the target node, must not be {@code null}.
-     */
-    @Override
-    public DependencySelector deriveChildSelector( DependencyCollectionContext context )
-    {
-        if ( depth >= 2 )
-        {
-            return this;
-        }
-
-        return new Maven3DirectScopeDependencySelector( scope, depth + 1 );
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + depth;
-        result = prime * result + ( ( scope == null ) ? 0 : scope.hashCode() );
-        return result;
-    }
-
-    @Override
-    public boolean equals( Object obj )
-    {
-        if ( this == obj )
-        {
-            return true;
-        }
-        if ( obj == null )
-        {
-            return false;
-        }
-        if ( getClass() != obj.getClass() )
-        {
-            return false;
-        }
-        Maven3DirectScopeDependencySelector other = (Maven3DirectScopeDependencySelector) obj;
-        if ( depth != other.depth )
-        {
-            return false;
-        }
-        if ( scope == null )
-        {
-            if ( other.scope != null )
-            {
-                return false;
-            }
-        }
-        else if ( !scope.equals( other.scope ) )
-        {
-            return false;
-        }
-        return true;
-    }
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/NearestVersionSelector.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/NearestVersionSelector.java
deleted file mode 100644
index 31af5b8..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/NearestVersionSelector.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictContext;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictItem;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.VersionSelector;
-import org.sonatype.aether.RepositoryException;
-import org.sonatype.aether.collection.UnsolvableVersionConflictException;
-import org.sonatype.aether.graph.DependencyFilter;
-import org.sonatype.aether.graph.DependencyNode;
-import org.sonatype.aether.util.graph.PathRecordingDependencyVisitor;
-import org.sonatype.aether.version.Version;
-import org.sonatype.aether.version.VersionConstraint;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public final class NearestVersionSelector
-    extends VersionSelector
-{
-
-    @Override
-    public void selectVersion( ConflictContext context )
-        throws RepositoryException
-    {
-        ConflictGroup group = new ConflictGroup();
-        for ( ConflictItem item : context.getItems() )
-        {
-            DependencyNode node = item.getNode();
-            VersionConstraint constraint = node.getVersionConstraint();
-
-            boolean backtrack = false;
-            boolean hardConstraint = !constraint.getRanges().isEmpty();
-//            boolean hardConstraint = constraint.getRange() != null;
-
-            if ( hardConstraint )
-            {
-                if ( group.constraints.add( constraint ) )
-                {
-                    if ( group.winner != null && !constraint.containsVersion( group.winner.getNode().getVersion() ) )
-                    {
-                        backtrack = true;
-                    }
-                }
-            }
-
-            if ( isAcceptable( group, node.getVersion() ) )
-            {
-                group.candidates.add( item );
-
-                if ( backtrack )
-                {
-                    backtrack( group, context );
-                }
-                else if ( group.winner == null || isNearer( item, group.winner ) )
-                {
-                    group.winner = item;
-                }
-            }
-            else if ( backtrack )
-            {
-                backtrack( group, context );
-            }
-        }
-        context.setWinner( group.winner );
-    }
-
-    private void backtrack( ConflictGroup group, ConflictContext context )
-        throws UnsolvableVersionConflictException
-    {
-        group.winner = null;
-
-        for ( Iterator<ConflictItem> it = group.candidates.iterator(); it.hasNext(); )
-        {
-            ConflictItem candidate = it.next();
-
-            if ( !isAcceptable( group, candidate.getNode().getVersion() ) )
-            {
-                it.remove();
-            }
-            else if ( group.winner == null || isNearer( candidate, group.winner ) )
-            {
-                group.winner = candidate;
-            }
-        }
-
-        if ( group.winner == null )
-        {
-            throw newFailure( context );
-        }
-    }
-
-    private boolean isAcceptable( ConflictGroup group, Version version )
-    {
-        for ( VersionConstraint constraint : group.constraints )
-        {
-            if ( !constraint.containsVersion( version ) )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private boolean isNearer( ConflictItem item1, ConflictItem item2 )
-    {
-        if ( item1.isSibling( item2 ) )
-        {
-            return item1.getNode().getVersion().compareTo( item2.getNode().getVersion() ) > 0;
-        }
-        else
-        {
-            return item1.getDepth() < item2.getDepth();
-        }
-    }
-
-    private UnsolvableVersionConflictException newFailure( final ConflictContext context )
-    {
-        DependencyFilter filter = ( node, parents ) -> context.isIncluded( node );
-        PathRecordingDependencyVisitor visitor = new PathRecordingDependencyVisitor( filter );
-        context.getRoot().accept( visitor );
-        return new UnsolvableVersionConflictException( visitor.getPaths(), context.conflictId );
-//        return new UnsolvableVersionConflictException( visitor.getPaths() );
-    }
-
-    static final class ConflictGroup
-    {
-
-        final Collection<VersionConstraint> constraints;
-
-        final Collection<ConflictItem> candidates;
-
-        ConflictItem winner;
-
-        ConflictGroup()
-        {
-            constraints = new HashSet<>();
-            candidates = new ArrayList<>( 64 );
-        }
-
-        @Override
-        public String toString()
-        {
-            return String.valueOf( winner );
-        }
-
-    }
-
-
-}
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/SimpleOptionalitySelector.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/SimpleOptionalitySelector.java
deleted file mode 100644
index d63df0b..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/SimpleOptionalitySelector.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.Collection;
-
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictContext;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictItem;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.OptionalitySelector;
-import org.sonatype.aether.RepositoryException;
-
-/**
- * This class is a copy of their homonymous in the Eclipse Aether library, adapted to work with Sonatype Aether.
- * 
- * @author Gabriel Belingueres
- * @since 3.1.0
- */
-public class SimpleOptionalitySelector
-    extends OptionalitySelector
-{
-
-    @Override
-    public void selectOptionality( ConflictContext context )
-        throws RepositoryException
-    {
-        boolean optional = chooseEffectiveOptionality( context.getItems() );
-        context.setOptional( optional );
-    }
-
-    private boolean chooseEffectiveOptionality( Collection<ConflictItem> items )
-    {
-        boolean optional = true;
-        for ( ConflictItem item : items )
-        {
-            if ( item.getDepth() <= 1 )
-            {
-                return item.getDependency().isOptional();
-            }
-            if ( ( item.getOptionalities() & ConflictItem.OPTIONAL_FALSE ) != 0 )
-            {
-                optional = false;
-            }
-        }
-        return optional;
-    }
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/VerboseJavaScopeSelector.java b/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/VerboseJavaScopeSelector.java
deleted file mode 100644
index 85b660d..0000000
--- a/src/main/java/org/apache/maven/shared/dependency/graph/internal/maven30/VerboseJavaScopeSelector.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.apache.maven.shared.dependency.graph.internal.maven30;
-
-/*
- * 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.
- */
-
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ConflictContext;
-import org.apache.maven.shared.dependency.graph.internal.maven30.ConflictResolver.ScopeSelector;
-import org.sonatype.aether.RepositoryException;
-
-/**
- * A JavaScopeSelector that keeps track of reduced scopes
- * 
- */
-public class VerboseJavaScopeSelector extends ScopeSelector
-{
-    public static final String REDUCED_SCOPE = "REDUCED_SCOPE";
-    
-    private final ScopeSelector scopeSelector = new JavaScopeSelector();
-
-    @Override
-    public void selectScope( ConflictContext context )
-        throws RepositoryException
-    {
-        scopeSelector.selectScope( context );
-        
-        context.getItems().stream()
-            .flatMap( i -> i.getScopes().stream() )
-            .distinct()
-            .max( new ScopeComparator() )
-            .filter( s -> s != context.getScope() )
-            .ifPresent( s -> context.getWinner().getNode().setData( REDUCED_SCOPE, s ) );
-    }
-    
-    static class ScopeComparator implements Comparator<String>
-    {
-        List<String> orderedScopes = Arrays.asList( "compile", "runtime", "provided", "test" );
-
-        @Override
-        public int compare( String lhs, String rhs )
-        {
-            return orderedScopes.indexOf( rhs ) - orderedScopes.indexOf( lhs );
-        }
-    }    
-}