You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2016/09/03 20:23:36 UTC

[13/51] [partial] maven-aether git commit: [MNG-6007] rename Aether to Maven Artifact Resolver

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
deleted file mode 100644
index 6ccc508..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
+++ /dev/null
@@ -1,1327 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.eclipse.aether.RepositoryException;
-import org.eclipse.aether.RepositorySystemSession;
-import org.eclipse.aether.artifact.Artifact;
-import org.eclipse.aether.collection.DependencyGraphTransformationContext;
-import org.eclipse.aether.collection.DependencyGraphTransformer;
-import org.eclipse.aether.graph.DefaultDependencyNode;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.ConfigUtils;
-
-/**
- * A dependency graph transformer that resolves version and scope conflicts among dependencies. For a given set of
- * conflicting nodes, one node will be chosen as the winner and the other nodes are removed from the dependency graph.
- * The exact rules by which a winning node and its effective scope are determined are controlled by user-supplied
- * implementations of {@link VersionSelector}, {@link ScopeSelector}, {@link OptionalitySelector} and
- * {@link ScopeDeriver}.
- * <p>
- * By default, this graph transformer will turn the dependency graph into a tree without duplicate artifacts. Using the
- * configuration property {@link #CONFIG_PROP_VERBOSE}, a verbose mode can be enabled where the graph is still turned
- * into a tree but all nodes participating in a conflict are retained. The nodes that were rejected during conflict
- * resolution have no children and link back to the winner node via the {@link #NODE_DATA_WINNER} key in their custom
- * data. Additionally, the keys {@link #NODE_DATA_ORIGINAL_SCOPE} and {@link #NODE_DATA_ORIGINAL_OPTIONALITY} are used
- * to store the original scope and optionality of each node. Obviously, the resulting dependency tree is not suitable
- * for artifact resolution unless a filter is employed to exclude the duplicate dependencies.
- * <p>
- * This transformer will query the keys {@link TransformationContextKeys#CONFLICT_IDS},
- * {@link TransformationContextKeys#SORTED_CONFLICT_IDS}, {@link TransformationContextKeys#CYCLIC_CONFLICT_IDS} for
- * existing information about conflict ids. In absence of this information, it will automatically invoke the
- * {@link ConflictIdSorter} to calculate it.
- */
-public final class ConflictResolver
-    implements DependencyGraphTransformer
-{
-
-    /**
-     * The key in the repository session's {@link 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.nanoTime();
-
-        @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<Object, Collection<Object>>();
-        for ( Collection<?> cycle : conflictIdCycles )
-        {
-            for ( Object conflictId : cycle )
-            {
-                Collection<Object> predecessors = cyclicPredecessors.get( conflictId );
-                if ( predecessors == null )
-                {
-                    predecessors = new HashSet<Object>();
-                    cyclicPredecessors.put( conflictId, predecessors );
-                }
-                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.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.nanoTime();
-            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<String>();
-                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<ConflictItem>( 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<Object>( conflictIdCount * 2 );
-            resolvedIds = new HashMap<Object, DependencyNode>( conflictIdCount * 2 );
-            items = new ArrayList<ConflictItem>( 256 );
-            infos = new IdentityHashMap<List<DependencyNode>, NodeInfo>( 64 );
-            stack = new IdentityHashMap<List<DependencyNode>, Object>( 64 );
-            parentNodes = new ArrayList<DependencyNode>( 64 );
-            parentScopes = new ArrayList<String>( 64 );
-            parentOptionals = new ArrayList<Boolean>( 64 );
-            parentInfos = new ArrayList<NodeInfo>( 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 = 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.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 = scopeCtx.childScope = scope( child );
-        }
-
-        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() : false;
-            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
-     * @noinstantiate 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}.
-         * @noreference 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 = this.childScope = ( childScope != null ) ? childScope : "";
-        }
-
-        /**
-         * 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.
-     * 
-     * @noinstantiate 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.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}.
-         * @noreference 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.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<Object>();
-                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
-     * @noinstantiate 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}.
-         * @noreference 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}.
-     * <p>
-     * <strong>Note:</strong> 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 must 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.
-     * <p>
-     * <strong>Note:</strong> 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 must 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.
-     * <p>
-     * <strong>Note:</strong> 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 must 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.
-     * <p>
-     * <strong>Note:</strong> 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 must 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;
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java
deleted file mode 100644
index d96e04e..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyContextRefiner.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.eclipse.aether.RepositoryException;
-import org.eclipse.aether.collection.DependencyGraphTransformationContext;
-import org.eclipse.aether.collection.DependencyGraphTransformer;
-import org.eclipse.aether.graph.Dependency;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.artifact.JavaScopes;
-
-/**
- * A dependency graph transformer that refines the request context for nodes that belong to the "project" context by
- * appending the classpath type to which the node belongs. For instance, a compile-time project dependency will be
- * assigned the request context "project/compile".
- * 
- * @see DependencyNode#getRequestContext()
- */
-public final class JavaDependencyContextRefiner
-    implements DependencyGraphTransformer
-{
-
-    public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
-        throws RepositoryException
-    {
-        String ctx = node.getRequestContext();
-
-        if ( "project".equals( ctx ) )
-        {
-            String scope = getClasspathScope( node );
-            if ( scope != null )
-            {
-                ctx += '/' + scope;
-                node.setRequestContext( ctx );
-            }
-        }
-
-        for ( DependencyNode child : node.getChildren() )
-        {
-            transformGraph( child, context );
-        }
-
-        return node;
-    }
-
-    private String getClasspathScope( DependencyNode node )
-    {
-        Dependency dependency = node.getDependency();
-        if ( dependency == null )
-        {
-            return null;
-        }
-
-        String scope = dependency.getScope();
-
-        if ( JavaScopes.COMPILE.equals( scope ) || JavaScopes.SYSTEM.equals( scope )
-            || JavaScopes.PROVIDED.equals( scope ) )
-        {
-            return JavaScopes.COMPILE;
-        }
-        else if ( JavaScopes.RUNTIME.equals( scope ) )
-        {
-            return JavaScopes.RUNTIME;
-        }
-        else if ( JavaScopes.TEST.equals( scope ) )
-        {
-            return JavaScopes.TEST;
-        }
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
deleted file mode 100644
index 441b6df..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaDependencyMediator.java
+++ /dev/null
@@ -1,389 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.collection.DependencyGraphTransformationContext;
-import org.eclipse.aether.collection.DependencyGraphTransformer;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.artifact.JavaScopes;
-
-/**
- * A {@code DependencyGraphTransformer} applying the Maven dependency mediation mechanism.
- *
- * @author Christian Schulte
- * @since 1.2
- * @see <a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">Introduction to the Dependency Mechanism</a>
- */
-public final class JavaDependencyMediator
-    implements DependencyGraphTransformer
-{
-
-    private static final Map<String, Integer> APPLICATION_SCOPE_PRIORITIES = new HashMap<String, Integer>( 5 );
-
-    private static final Map<String, Integer> TEST_SCOPE_PRIORITIES = new HashMap<String, Integer>( 5 );
-
-    static
-    {
-        APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.TEST, 0 );
-        APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.RUNTIME, 1 );
-        APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.PROVIDED, 2 );
-        APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.COMPILE, 3 );
-        APPLICATION_SCOPE_PRIORITIES.put( JavaScopes.SYSTEM, 4 );
-
-        TEST_SCOPE_PRIORITIES.put( JavaScopes.RUNTIME, 0 );
-        TEST_SCOPE_PRIORITIES.put( JavaScopes.PROVIDED, 1 );
-        TEST_SCOPE_PRIORITIES.put( JavaScopes.COMPILE, 2 );
-        TEST_SCOPE_PRIORITIES.put( JavaScopes.TEST, 3 );
-        TEST_SCOPE_PRIORITIES.put( JavaScopes.SYSTEM, 4 );
-    }
-
-    /**
-     * Application scope nodes are prioritized over non application scope nodes.
-     */
-    public static final int APPLICATION_SCOPE_PRIORITIZATION = 1 << 1;
-
-    /**
-     * Test scope nodes are prioritized over non test scope nodes.
-     */
-    public static final int TEST_SCOPE_PRIORITIZATION = 1 << 2;
-
-    /**
-     * Nearest wins only strategy. No scopes are prioritized.
-     */
-    public static final int NO_PRIORITIZATION = 1 << 3;
-
-    /**
-     * The prioritization to apply.
-     */
-    private final int prioritization;
-
-    /**
-     * Creates a new {@code DependencyGraphTransformer}.
-     *
-     * @param prioritization The prioritization to apply.
-     *
-     * @see #APPLICATION_SCOPE_PRIORITIZATION
-     * @see #TEST_SCOPE_PRIORITIZATION
-     * @see #NO_PRIORITIZATION
-     */
-    public JavaDependencyMediator( final int prioritization )
-    {
-        super();
-        this.prioritization = prioritization;
-    }
-
-    @Override
-    public DependencyNode transformGraph( final DependencyNode node,
-                                          final DependencyGraphTransformationContext context )
-        throws RepositoryException
-    {
-        DependencyNode result = node;
-        result = this.removeNonTransitiveNodes( result );
-        result = this.updateTransitiveScopes( result );
-
-        for ( ;; )
-        {
-            if ( this.removeDuplicateNodes( result, result, new HashMap<ConflictMarker.Key, DependencyNode>( 8192 ),
-                                            new HashMap<DependencyNode, DependencyNode>( 8192 ) ) )
-            {
-                break;
-            }
-        }
-
-        return result;
-    }
-
-    private DependencyNode removeNonTransitiveNodes( final DependencyNode parent )
-    {
-        final String parentScope = parent.getDependency() != null
-                                       ? parent.getDependency().getScope() != null
-                                             && parent.getDependency().getScope().length() >= 0
-                                             ? parent.getDependency().getScope()
-                                             : JavaScopes.COMPILE
-                                       : null;
-
-        for ( final Iterator<DependencyNode> it = parent.getChildren().iterator(); it.hasNext(); )
-        {
-            final DependencyNode child = it.next();
-
-            recurse:
-            {
-                if ( parentScope != null )
-                {
-                    String childScope = child.getDependency().getScope() != null
-                                            && child.getDependency().getScope().length() >= 0
-                                            ? child.getDependency().getScope()
-                                            : JavaScopes.COMPILE;
-
-                    // Provided and test scopes are non-transitive.
-                    // Optional dependencies are non-transitive.
-                    if ( JavaScopes.PROVIDED.equals( childScope )
-                             || JavaScopes.TEST.equals( childScope )
-                             || child.getDependency().isOptional() )
-                    {
-                        it.remove();
-                        break recurse;
-                    }
-                }
-
-                this.removeNonTransitiveNodes( child );
-            }
-        }
-
-        return parent;
-    }
-
-    private DependencyNode updateTransitiveScopes( final DependencyNode parent )
-    {
-        final String parentScope = parent.getDependency() != null
-                                       ? parent.getDependency().getScope() != null
-                                             && parent.getDependency().getScope().length() >= 0
-                                             ? parent.getDependency().getScope()
-                                             : JavaScopes.COMPILE
-                                       : null;
-
-        for ( final DependencyNode child : parent.getChildren() )
-        {
-            if ( parentScope != null )
-            {
-                String childScope = child.getDependency().getScope() != null
-                                        && child.getDependency().getScope().length() >= 0
-                                        ? child.getDependency().getScope()
-                                        : JavaScopes.COMPILE;
-
-                if ( ( child.getManagedBits() & DependencyNode.MANAGED_SCOPE ) == 0 )
-                {
-                    // Non-managed child scopes are updated according to the table in the "Dependency Scope" section
-                    // of the "Introduction to the Dependency Mechanism" document.
-
-                    if ( JavaScopes.PROVIDED.equals( parentScope ) )
-                    {
-                        // Compile and runtime become provided.
-                        if ( JavaScopes.COMPILE.equals( childScope )
-                                 || JavaScopes.RUNTIME.equals( childScope ) )
-                        {
-                            childScope = JavaScopes.PROVIDED;
-                            child.setScope( childScope );
-                        }
-                    }
-                    else if ( JavaScopes.RUNTIME.equals( parentScope ) )
-                    {
-                        // Compile becomes runtime.
-                        if ( JavaScopes.COMPILE.equals( childScope ) )
-                        {
-                            childScope = JavaScopes.RUNTIME;
-                            child.setScope( childScope );
-                        }
-                    }
-                    else if ( JavaScopes.TEST.equals( parentScope ) )
-                    {
-                        // Compile and runtime become test.
-                        if ( JavaScopes.COMPILE.equals( childScope )
-                                 || JavaScopes.RUNTIME.equals( childScope ) )
-                        {
-                            childScope = JavaScopes.TEST;
-                            child.setScope( childScope );
-                        }
-                    }
-                }
-            }
-
-            this.updateTransitiveScopes( child );
-        }
-
-        return parent;
-    }
-
-    private boolean removeDuplicateNodes( final DependencyNode rootNode,
-                                          final DependencyNode candidateNode,
-                                          final Map<ConflictMarker.Key, DependencyNode> winnerNodes,
-                                          final Map<DependencyNode, DependencyNode> looserNodes )
-    {
-        boolean restart = false;
-
-        recurse:
-        {
-            if ( candidateNode.getDependency() != null )
-            {
-                final ConflictMarker.Key candidateKey = new ConflictMarker.Key( candidateNode.getArtifact() );
-                final DependencyNode winnerNode = winnerNodes.get( candidateKey );
-
-                if ( winnerNode == null )
-                {
-                    // Conflict not yet seen. Candidate is selected.
-                    winnerNodes.put( candidateKey, candidateNode );
-                }
-                else if ( this.isPreferredNode( winnerNode, candidateNode ) )
-                {
-                    // Conflict already seen. Candidate is preferred.
-                    winnerNodes.put( candidateKey, candidateNode );
-                    looserNodes.put( candidateNode, winnerNode );
-
-                    if ( winnerNode.getParent() != null )
-                    {
-                        winnerNode.getParent().getChildren().remove( winnerNode );
-                    }
-                    else
-                    {
-                        rootNode.getChildren().remove( winnerNode );
-                    }
-
-                    final DependencyNode winningChild = getWinningChild( winnerNode, winnerNodes.values() );
-
-                    if ( winningChild != null )
-                    {
-                        // The node eliminated by the current candidate node contains a child node which has been
-                        // selected the winner in a previous iteration. As that winner is eliminated in this iteration,
-                        // the former looser needs to be re-added and the whole transformation re-started (undo and
-                        // restart). No need to maintain the maps here because they are thrown away when restarting.
-                        // Doing it for completeness, however.
-                        final DependencyNode looserNode = looserNodes.remove( winningChild ); // Can be get().
-
-                        if ( looserNode != null )
-                        {
-                            if ( looserNode.getParent() != null )
-                            {
-                                if ( !looserNode.getParent().getChildren().contains( looserNode ) )
-                                {
-                                    looserNode.getParent().getChildren().add( looserNode );
-                                }
-                            }
-                            else if ( !rootNode.getChildren().contains( looserNode ) )
-                            {
-                                rootNode.getChildren().add( looserNode );
-                            }
-
-                            // Not needed, but...
-                            final DependencyNode winner =
-                                winnerNodes.remove( new ConflictMarker.Key( looserNode.getArtifact() ) );
-
-                            if ( winner != null )
-                            {
-                                looserNodes.remove( winner );
-                            }
-                        }
-
-                        restart = true;
-                        break recurse;
-                    }
-                }
-                else
-                {
-                    // Conflict already seen. Candidate is not preferred.
-                    looserNodes.put( winnerNode, candidateNode );
-                    if ( candidateNode.getParent() != null )
-                    {
-                        candidateNode.getParent().getChildren().remove( candidateNode );
-                    }
-                    else
-                    {
-                        rootNode.getChildren().remove( candidateNode );
-                    }
-                    // No need to inspect children.
-                    break recurse;
-                }
-            }
-
-            for ( final DependencyNode child : new ArrayList<DependencyNode>( candidateNode.getChildren() ) )
-            {
-                if ( !this.removeDuplicateNodes( rootNode, child, winnerNodes, looserNodes ) )
-                {
-                    restart = true;
-                    break recurse;
-                }
-            }
-        }
-
-        return !restart;
-    }
-
-    private boolean isPreferredNode( final DependencyNode existing, final DependencyNode candidate )
-    {
-        boolean preferred = false;
-        Integer p1 = null;
-        Integer p2 = null;
-        boolean prioritize = true;
-
-        if ( this.prioritization == APPLICATION_SCOPE_PRIORITIZATION )
-        {
-            p1 = APPLICATION_SCOPE_PRIORITIES.get( existing.getDependency().getScope() );
-            p2 = APPLICATION_SCOPE_PRIORITIES.get( candidate.getDependency().getScope() );
-        }
-        else if ( this.prioritization == TEST_SCOPE_PRIORITIZATION )
-        {
-            p1 = TEST_SCOPE_PRIORITIES.get( existing.getDependency().getScope() );
-            p2 = TEST_SCOPE_PRIORITIES.get( candidate.getDependency().getScope() );
-        }
-        else if ( this.prioritization == NO_PRIORITIZATION )
-        {
-            prioritize = false;
-        }
-        else
-        {
-            throw new AssertionError( this.prioritization );
-        }
-
-        final Boolean candidateScopePrioritized = p1 != null && p2 != null ? p2 > p1 : false;
-        final boolean equalPriority =
-            existing.getDependency().getScope().equals( candidate.getDependency().getScope() );
-
-        if ( candidate.getDepth() < existing.getDepth() )
-        {
-            preferred = !prioritize || equalPriority || candidateScopePrioritized;
-        }
-        else if ( candidate.getDepth() == existing.getDepth() )
-        {
-            preferred = prioritize && !equalPriority && candidateScopePrioritized;
-        }
-
-        return preferred;
-    }
-
-    private static DependencyNode getWinningChild( final DependencyNode node,
-                                                   final Collection<DependencyNode> winnerNodes )
-    {
-        DependencyNode winningChild = winnerNodes.contains( node )
-                                          ? node
-                                          : null;
-
-        if ( winningChild == null )
-        {
-            for ( final DependencyNode child : node.getChildren() )
-            {
-                winningChild = getWinningChild( child, winnerNodes );
-
-                if ( winningChild != null )
-                {
-                    break;
-                }
-            }
-        }
-
-        return winningChild;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java
deleted file mode 100644
index 4c5fd3e..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeDeriver.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.eclipse.aether.RepositoryException;
-import org.eclipse.aether.util.artifact.JavaScopes;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeContext;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeDeriver;
-
-/**
- * A scope deriver for use with {@link ConflictResolver} that supports the scopes from {@link JavaScopes}.
- */
-public final class JavaScopeDeriver
-    extends ScopeDeriver
-{
-
-    /**
-     * Creates a new instance of this scope deriver.
-     */
-    public JavaScopeDeriver()
-    {
-    }
-
-    @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;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java
deleted file mode 100644
index 93edf05..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/JavaScopeSelector.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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.eclipse.aether.RepositoryException;
-import org.eclipse.aether.util.artifact.JavaScopes;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictContext;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictItem;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ScopeSelector;
-
-/**
- * A scope selector for use with {@link ConflictResolver} that supports the scopes from {@link JavaScopes}. In general,
- * this selector picks the widest scope present among conflicting dependencies where e.g. "compile" is wider than
- * "runtime" which is wider than "test". If however a direct dependency is involved, its scope is selected.
- */
-public final class JavaScopeSelector
-    extends ScopeSelector
-{
-
-    /**
-     * Creates a new instance of this scope selector.
-     */
-    public JavaScopeSelector()
-    {
-    }
-
-    @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<String>();
-        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;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/maven-aether/blob/27f8bd73/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java
----------------------------------------------------------------------
diff --git a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java b/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java
deleted file mode 100644
index c1ffa85..0000000
--- a/aether-util/src/main/java/org/eclipse/aether/util/graph/transformer/NearestVersionSelector.java
+++ /dev/null
@@ -1,185 +0,0 @@
-package org.eclipse.aether.util.graph.transformer;
-
-/*
- * 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 java.util.List;
-
-import org.eclipse.aether.RepositoryException;
-import org.eclipse.aether.collection.UnsolvableVersionConflictException;
-import org.eclipse.aether.graph.DependencyFilter;
-import org.eclipse.aether.graph.DependencyNode;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictContext;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.ConflictItem;
-import org.eclipse.aether.util.graph.transformer.ConflictResolver.VersionSelector;
-import org.eclipse.aether.util.graph.visitor.PathRecordingDependencyVisitor;
-import org.eclipse.aether.version.Version;
-import org.eclipse.aether.version.VersionConstraint;
-
-/**
- * A version selector for use with {@link ConflictResolver} that resolves version conflicts using a nearest-wins
- * strategy. If there is no single node that satisfies all encountered version ranges, the selector will fail.
- */
-public final class NearestVersionSelector
-    extends VersionSelector
-{
-
-    /**
-     * Creates a new instance of this version selector.
-     */
-    public NearestVersionSelector()
-    {
-    }
-
-    @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.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 = new DependencyFilter()
-        {
-            public boolean accept( DependencyNode node, List<DependencyNode> parents )
-            {
-                return context.isIncluded( node );
-            }
-        };
-        PathRecordingDependencyVisitor visitor = new PathRecordingDependencyVisitor( filter );
-        context.getRoot().accept( visitor );
-        return new UnsolvableVersionConflictException( visitor.getPaths() );
-    }
-
-    static final class ConflictGroup
-    {
-
-        final Collection<VersionConstraint> constraints;
-
-        final Collection<ConflictItem> candidates;
-
-        ConflictItem winner;
-
-        public ConflictGroup()
-        {
-            constraints = new HashSet<VersionConstraint>();
-            candidates = new ArrayList<ConflictItem>( 64 );
-        }
-
-        @Override
-        public String toString()
-        {
-            return String.valueOf( winner );
-        }
-
-    }
-
-}