package org.apache.maven.shared.dependency.tree;

/*
 * 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.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import junit.framework.AssertionFailedError;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.DefaultArtifactRepository;
import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
import org.apache.maven.artifact.resolver.ArtifactCollector;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ResolutionNode;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.PlexusTestCase;

/**
 * Tests <code>DefaultDependencyTreeBuilder</code>.
 * 
 * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
 * @version $Id$
 * @see DefaultDependencyTreeBuilder
 */
public class DefaultDependencyTreeBuilderTest
    extends PlexusTestCase
{
    // fields -----------------------------------------------------------------

    private DefaultDependencyTreeBuilder builder;

    private ArtifactRepository artifactRepository;

    private ArtifactFactory artifactFactory;

    private ArtifactMetadataSourceStub artifactMetadataSource;

    private ArtifactCollector artifactCollector;

    // TestCase methods -------------------------------------------------------

    /**
     * {@inheritDoc}
     */
    protected void setUp()
        throws Exception
    {
        super.setUp();

        builder = (DefaultDependencyTreeBuilder) lookup( DependencyTreeBuilder.ROLE );

        String repositoryURL = getTestFile( "target/local-repo" ).toURI().toString();
        artifactRepository = new DefaultArtifactRepository( "local", repositoryURL, new DefaultRepositoryLayout() );

        artifactFactory = (ArtifactFactory) lookup( ArtifactFactory.ROLE );
        artifactMetadataSource = new ArtifactMetadataSourceStub();
        artifactCollector = (ArtifactCollector) lookup( ArtifactCollector.class.getName() );
    }

    /**
     * {@inheritDoc}
     */
    protected void tearDown()
        throws Exception
    {
        super.tearDown();

        builder = null;
    }

    // tests ------------------------------------------------------------------

    /**
     * Tests building a tree for a project with one dependency:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     * </pre>
     * 
     * @throws DependencyTreeBuilderException 
     */
    public void testProjectWithDependency()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        expectedRootNode.addChild( createNode( "g:a:t:1" ) );

        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with one transitive dependency:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    \- g:b:t:1
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithTransitiveDependency()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact transitiveArtifact = createArtifact( "g:b:t:1" );
        addArtifactMetadata( childArtifact, transitiveArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        childArtifactNode.addChild( createNode( "g:b:t:1" ) );

        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with a duplicate transitive dependency:
     * 
     * <pre>
     * g:p:t:1
     * +- g:a:t:1
     * |  \- g:c:t:1
     * \- g:b:t:1
     *    \- (g:c:t:1 - omitted for duplicate)
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithDuplicateDependency()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact child1Artifact = createArtifact( "g:a:t:1" );
        Artifact transitiveArtifact = createArtifact( "g:c:t:1" );
        Artifact child2Artifact = createArtifact( "g:b:t:1" );
        Artifact duplicateTransitiveArtifact = createArtifact( "g:c:t:1" );
        addArtifactMetadata( child1Artifact, transitiveArtifact );
        addArtifactMetadata( child2Artifact, duplicateTransitiveArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { child1Artifact, child2Artifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode child1ArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( child1ArtifactNode );
        DependencyNode transitiveArtifactNode = createNode( "g:c:t:1" );
        child1ArtifactNode.addChild( transitiveArtifactNode );
        DependencyNode child2ArtifactNode = createNode( "g:b:t:1" );
        expectedRootNode.addChild( child2ArtifactNode );
        child2ArtifactNode.addChild( createNode( "g:c:t:1", DependencyNode.OMITTED_FOR_DUPLICATE, transitiveArtifactNode.getArtifact() ) );

        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with a dependency that has conflicting versions, where the nearest is
     * encountered first:
     * 
     * <pre>
     * g:p:t:1
     * +- g:a:t:1
     * \- g:b:t:1
     *    \- (g:a:t:2 - omitted for conflict with 1)
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithConflictDependencyVersionFirstWins()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact nearestArtifact = createArtifact( "g:a:t:1" );
        Artifact childArtifact = createArtifact( "g:b:t:1" );
        Artifact farthestArtifact = createArtifact( "g:a:t:2" );
        addArtifactMetadata( childArtifact, farthestArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { nearestArtifact, childArtifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode nearestArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( nearestArtifactNode );
        DependencyNode childArtifactNode = createNode( "g:b:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        childArtifactNode.addChild( createNode( "g:a:t:2", DependencyNode.OMITTED_FOR_CONFLICT, nearestArtifactNode.getArtifact() ) );

        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with a dependency that has conflicting versions, where the nearest is
     * encountered last:
     * 
     * <pre>
     * g:p:t:1
     * +- g:a:t:1
     * |  \- (g:b:t:2 - omitted for conflict with 1)
     * \- g:b:t:1
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithConflictDependencyVersionLastWins()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact farthestArtifact = createArtifact( "g:b:t:2" );
        Artifact nearestArtifact = createArtifact( "g:b:t:1" );
        addArtifactMetadata( childArtifact, farthestArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact, nearestArtifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode farthestArtifactNode = createNode( "g:b:t:1" );
        expectedRootNode.addChild( farthestArtifactNode );
        childArtifactNode.addChild( createNode( "g:b:t:2", DependencyNode.OMITTED_FOR_CONFLICT, farthestArtifactNode.getArtifact() ) );

        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with a dependency that has conflicting scopes, where the nearest is not
     * broadened since it is defined in the top-level POM:
     * 
     * <pre>
     * g:p:t:1
     * +- g:b:t:1:test (scope not updated to compile)
     * \- g:a:t:1
     *    \- (g:b:t:1:compile - omitted for duplicate)
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithConflictDependencyScopeCurrentPom()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact nearestArtifact = createArtifact( "g:b:t:1:test" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact farthestArtifact = createArtifact( "g:b:t:1:compile" );
        addArtifactMetadata( childArtifact, farthestArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { nearestArtifact, childArtifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode nearestArtifactNode = createNode( "g:b:t:1:test" );
        nearestArtifactNode.setFailedUpdateScope( "compile" );
        expectedRootNode.addChild( nearestArtifactNode );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        childArtifactNode.addChild( createNode( "g:b:t:1:compile", DependencyNode.OMITTED_FOR_DUPLICATE, nearestArtifactNode.getArtifact() ) );
        
        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with a dependency that has conflicting scopes, where the winner is
     * encountered first:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    +- g:b:t:1
     *    |  \- g:c:t:1:compile
     *    \- (g:c:t:1:compile - scope updated from test; omitted for duplicate)
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithConflictDependencyScopeFirstWins()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact grandchildArtifact = createArtifact( "g:b:t:1" );
        Artifact farthestArtifact = createArtifact( "g:c:t:1:compile" );
        Artifact nearestArtifact = createArtifact( "g:c:t:1:test" );
        addArtifactMetadata( childArtifact, new Artifact[] { grandchildArtifact, nearestArtifact } );
        addArtifactMetadata( grandchildArtifact, farthestArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );

        /*
         * TODO: Not entirely convinced that the expected tree is correct - I would have expected:
         * 
         * <pre>
         * g:p:t:1
         * \- g:a:t:1
         *    +- g:b:t:1
         *    |  \- (g:c:t:1:compile - omitted for duplicate)
         *    \- g:c:t:1:compile (scope updated from test)
         * </pre>
         * 
         * @see http://www.mail-archive.com/dev@maven.apache.org/msg68011.html
         */
        /*
        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode grandchildArtifactNode = createNode( "g:b:t:1" );
        childArtifactNode.addChild( grandchildArtifactNode );
        DependencyNode nearestArtifactNode = createNode( "g:c:t:1:compile" );
        DependencyNode farthestArtifactNode = createNode( "g:c:t:1:compile", DependencyNode.OMITTED_FOR_DUPLICATE, nearestArtifactNode.getArtifact() );
        grandchildArtifactNode.addChild( farthestArtifactNode );
        nearestArtifactNode.setOriginalScope( "test" );
        childArtifactNode.addChild( nearestArtifactNode );
        */

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode grandchildArtifactNode = createNode( "g:b:t:1" );
        childArtifactNode.addChild( grandchildArtifactNode );
        DependencyNode farthestArtifactNode = createNode( "g:c:t:1:compile" );
        grandchildArtifactNode.addChild( farthestArtifactNode );
        DependencyNode nearestArtifactNode = createNode( "g:c:t:1:compile", DependencyNode.OMITTED_FOR_DUPLICATE, farthestArtifactNode.getArtifact() );
        nearestArtifactNode.setOriginalScope( "test" );
        childArtifactNode.addChild( nearestArtifactNode );
        
        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with a dependency that has conflicting scopes, where the winner is
     * encountered last:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    +- (g:c:t:1:compile - scope updated from test; omitted for duplicate)
     *    \- g:b:t:1
     *       \- g:c:t:1:compile
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithConflictDependencyScopeLastWins()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact nearestArtifact = createArtifact( "g:c:t:1:test" );
        Artifact grandchildArtifact = createArtifact( "g:b:t:1" );
        Artifact farthestArtifact = createArtifact( "g:c:t:1:compile" );
        addArtifactMetadata( childArtifact, new Artifact[] { nearestArtifact, grandchildArtifact } );
        addArtifactMetadata( grandchildArtifact, farthestArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );

        /*
         * TODO: Not entirely convinced that the expected tree is correct - I would have expected:
         * 
         * <pre>
         * g:p:t:1
         * \- g:a:t:1
         *    +- g:c:t:1:compile (scope updated from test)
         *    \- g:b:t:1
         *       \- (g:c:t:1:compile - omitted for duplicate)
         * </pre>
         * 
         * @see http://www.mail-archive.com/dev@maven.apache.org/msg68011.html
         */
        /*
        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode nearestArtifactNode = createNode( "g:c:t:1:compile" );
        nearestArtifactNode.setOriginalScope( "test" );
        childArtifactNode.addChild( nearestArtifactNode );
        DependencyNode grandchildArtifactNode = createNode( "g:b:t:1" );
        childArtifactNode.addChild( grandchildArtifactNode );
        grandchildArtifactNode.addChild( createNode( "g:c:t:1:compile", DependencyNode.OMITTED_FOR_DUPLICATE, nearestArtifactNode.getArtifact() ) );
        */
        
        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode farthestArtifactNode = createNode( "g:c:t:1:compile" );
        DependencyNode nearestArtifactNode = createNode( "g:c:t:1:compile", DependencyNode.OMITTED_FOR_DUPLICATE, farthestArtifactNode.getArtifact() );
        nearestArtifactNode.setOriginalScope( "test" );
        childArtifactNode.addChild( nearestArtifactNode );
        DependencyNode grandchildArtifactNode = createNode( "g:b:t:1" );
        childArtifactNode.addChild( grandchildArtifactNode );
        grandchildArtifactNode.addChild( farthestArtifactNode );
        
        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with one transitive dependency whose version is fixed in dependency
     * management:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    \- g:b:t:2 (version managed from 1)
     * </pre>
     * 
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithManagedTransitiveDependencyVersion()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact transitiveArtifact = createArtifact( "g:b:t:1" );
        Artifact managedTransitiveArtifact = createArtifact( "g:b:t:2" );
        addArtifactMetadata( childArtifact, transitiveArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );
        setManagedVersionMap( project, Collections.singleton( managedTransitiveArtifact ) );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode managedTransitiveArtifactNode = createNode( "g:b:t:2" );
        managedTransitiveArtifactNode.setPremanagedVersion( "1" );
        childArtifactNode.addChild( managedTransitiveArtifactNode );

        assertDependencyTree( expectedRootNode, project );
    }

    // TODO: see MNG-3548
    /**
     * Tests building a tree for a project with a dependency that is duplicated and the version is also fixed in 
     * dependency management:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    +- g:b:t:1
     *    |  \- (g:c:t:2 - version managed from 1; omitted for duplicate)
     *    \- g:c:t:2 (version managed from 1)
     * </pre>
     * 
     * @throws DependencyTreeBuilderException
     */
    /*
    public void testProjectWithManagedTransitiveDependencyVersionAndDuplicate() throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact grandchildArtifact = createArtifact( "g:b:t:1" );
        Artifact farthestTransitiveArtifact = createArtifact( "g:c:t:1" );
        Artifact nearestTransitiveArtifact = createArtifact( "g:c:t:1" );
        Artifact managedTransitiveArtifact = createArtifact( "g:c:t:2" );
        addArtifactMetadata( childArtifact, new Artifact[] { grandchildArtifact, nearestTransitiveArtifact } );
        addArtifactMetadata( grandchildArtifact, farthestTransitiveArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );
        setManagedVersionMap( project, Collections.singleton( managedTransitiveArtifact ) );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode grandchildArtifactNode = createNode( "g:b:t:2" );
        childArtifactNode.addChild( grandchildArtifactNode );
        DependencyNode managedTransitiveArtifactNode = createNode( "g:c:t:2" );
        managedTransitiveArtifactNode.setPremanagedVersion( "1" );
        childArtifactNode.addChild( managedTransitiveArtifactNode );
        DependencyNode omittedManagedTransitiveArtifactNode = createNode( "g:c:t:2" );
        omittedManagedTransitiveArtifactNode.setPremanagedVersion( "1" );
        omittedManagedTransitiveArtifactNode.omitForConflict( managedTransitiveArtifact );
        grandchildArtifactNode.addChild( omittedManagedTransitiveArtifactNode );

        assertDependencyTree( expectedRootNode, project );
    }
    */

    /**
     * Tests building a tree for a project with one transitive dependency whose scope is fixed in dependency management:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    \- g:b:t:1:test (scope managed from compile)
     * </pre>
     *
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithManagedTransitiveDependencyScope()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact transitiveArtifact = createArtifact( "g:b:t:1:compile" );
        Artifact managedTransitiveArtifact = createArtifact( "g:b:t:1:test" );
        addArtifactMetadata( childArtifact, transitiveArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );
        setManagedVersionMap( project, Collections.singleton( managedTransitiveArtifact ) );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode managedTransitiveArtifactNode = createNode( "g:b:t:1:test" );
        managedTransitiveArtifactNode.setPremanagedScope( "compile" );
        childArtifactNode.addChild( managedTransitiveArtifactNode );

        assertDependencyTree( expectedRootNode, project );
    }

    /**
     * Tests building a tree for a project with one transitive dependency whose version and scope are fixed in
     * dependency management:
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     *    \- g:b:t:2:test (version managed from 1; scope managed from compile)
     * </pre>
     * 
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithManagedTransitiveDependencyVersionAndScope()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:1" );
        Artifact transitiveArtifact = createArtifact( "g:b:t:1:compile" );
        Artifact managedTransitiveArtifact = createArtifact( "g:b:t:2:test" );
        addArtifactMetadata( childArtifact, transitiveArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );
        setManagedVersionMap( project, Collections.singleton( managedTransitiveArtifact ) );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode managedTransitiveArtifactNode = createNode( "g:b:t:2:test" );
        managedTransitiveArtifactNode.setPremanagedVersion( "1" );
        managedTransitiveArtifactNode.setPremanagedScope( "compile" );
        childArtifactNode.addChild( managedTransitiveArtifactNode );

        assertDependencyTree( expectedRootNode, project );
    }
    
    /**
     * Tests building a tree for a project with a dependency that has conflicting versions and the version is also fixed
     * in dependency management:
     * 
     * <pre>
     * g:p:t:1
     * +- g:a:t:1
     * \- g:b:t:1
     *    \- (g:a:t:3 - version managed from 2; omitted for conflict with 1)
     * </pre>
     * 
     * @throws DependencyTreeBuilderException
     */
    public void testProjectWithManagedTransitiveDependencyVersionAndConflictDependencyVersion()
        throws DependencyTreeBuilderException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact nearestArtifact = createArtifact( "g:a:t:1" );
        Artifact childArtifact = createArtifact( "g:b:t:1" );
        Artifact farthestArtifact = createArtifact( "g:a:t:2" );
        Artifact managedTransitiveArtifact = createArtifact( "g:a:t:3" );
        addArtifactMetadata( childArtifact, farthestArtifact );

        MavenProject project = createProject( projectArtifact, new Artifact[] { nearestArtifact, childArtifact } );
        setManagedVersionMap( project, Collections.singleton( managedTransitiveArtifact ) );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode nearestArtifactNode = createNode( "g:a:t:1" );
        expectedRootNode.addChild( nearestArtifactNode );
        DependencyNode childArtifactNode = createNode( "g:b:t:1" );
        expectedRootNode.addChild( childArtifactNode );
        DependencyNode managedTransitiveArtifactNode = createNode( "g:a:t:3", DependencyNode.OMITTED_FOR_CONFLICT, nearestArtifactNode.getArtifact() );
        managedTransitiveArtifactNode.setPremanagedVersion( "2" );
        childArtifactNode.addChild( managedTransitiveArtifactNode );

        assertDependencyTree( expectedRootNode, project );
    }

    
    /**
     * Tests building a tree for a project with a dependency with version range
     * 
     * <pre>
     * g:p:t:1
     * \- g:a:t:1
     * </pre>
     * 
     * @throws InvalidVersionSpecificationException 
     * @throws DependencyTreeBuilderException 
     */
    public void testProjectWithVersionRange()
        throws InvalidVersionSpecificationException, DependencyTreeBuilderException
    {
        String range = "[1,2)";
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact childArtifact = createArtifact( "g:a:t:" + range);

        MavenProject project = createProject( projectArtifact, new Artifact[] { childArtifact } );

        ArtifactVersion version = new DefaultArtifactVersion( "1.0" );
        List<ArtifactVersion> availableVersions = new ArrayList<ArtifactVersion>();
        availableVersions.add( version );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        DependencyNode childNode = createNode( "g:a:t:1.0" );
        childNode.setAvailableVersions( availableVersions );
        childNode.setVersionSelectedFromRange( VersionRange.createFromVersionSpec( range ) );
        expectedRootNode.addChild( childNode );

        artifactMetadataSource.addAvailableVersions( childArtifact, availableVersions );
        assertDependencyTree( expectedRootNode, project );
    }

    // TODO: reinstate when MNG-3236 fixed
    /*
    public void testProjectWithFilter() throws DependencyTreeBuilderException, ArtifactResolutionException
    {
        Artifact projectArtifact = createArtifact( "g:p:t:1" );
        Artifact child1Artifact = createArtifact( "g:a:t:1" );
        Artifact child2Artifact = createArtifact( "g:b:t:1:test" );

        MavenProject project = createProject( projectArtifact, new Artifact[] { child1Artifact, child2Artifact } );

        DependencyNode expectedRootNode = createNode( "g:p:t:1" );
        expectedRootNode.addChild( createNode( "g:a:t:1" ) );

        ArtifactFilter artifactFilter = new ScopeArtifactFilter( Artifact.SCOPE_COMPILE );
        
        assertDependencyTree( expectedRootNode, project, artifactFilter );
    }
    */

    // private methods --------------------------------------------------------
    
    private DependencyNode createNode( String id )
    {
        return createNode( id, DependencyNode.INCLUDED, null );
    }
    
    private DependencyNode createNode( String id, int state, Artifact relatedArtifact )
    {
        return new DependencyNode( createArtifact( id ), state, relatedArtifact );
    }
    
    private Artifact createArtifact( String id )
    {
        String[] tokens = id.split( ":" );

        String groupId = get( tokens, 0 );
        String artifactId = get( tokens, 1 );
        String type = get( tokens, 2, "jar" );
        String version = get( tokens, 3 );
        String scope = get( tokens, 4 );
        
        VersionRange versionRange;
        try
        {
            versionRange = VersionRange.createFromVersionSpec( version );
        }
        catch ( InvalidVersionSpecificationException e )
        {
            throw new RuntimeException(e);
        }

        return new DefaultArtifact( groupId, artifactId, versionRange, scope, type, null, new DefaultArtifactHandler() );
    }
    
    private MavenProject createProject( Artifact projectArtifact, Artifact[] dependencyArtifacts )
    {
        MavenProject project = new MavenProject();
        project.setArtifact( projectArtifact );
        // LinkedHashSet since order is significant when omitting conflicts
        project.setDependencyArtifacts( new LinkedHashSet<Artifact>( Arrays.asList( dependencyArtifacts ) ) );
        project.setManagedVersionMap( new HashMap<String, Artifact>() );
        project.setRemoteArtifactRepositories( Collections.EMPTY_LIST );
        return project;
    }

    private void addArtifactMetadata( Artifact artifact, Artifact dependencyArtifact )
    {
        addArtifactMetadata( artifact, new Artifact[] { dependencyArtifact } );
    }
    
    private void addArtifactMetadata( Artifact artifact, Artifact[] dependencyArtifacts )
    {
        addArtifactMetadata( artifact, new LinkedHashSet<Artifact>( Arrays.asList( dependencyArtifacts ) ) );
    }
    
    private void addArtifactMetadata( Artifact artifact, Set<Artifact> dependencyArtifacts )
    {
        artifactMetadataSource.addArtifactMetadata( artifact, dependencyArtifacts );
    }
    
    private void setManagedVersionMap( MavenProject project, Set<Artifact> managedArtifacts )
    {
        Map<String, Artifact> managedVersionMap = new HashMap<String, Artifact>();
        
        for ( Artifact artifact : managedArtifacts )
        {
            String managementKey = getManagementKey( artifact );
            
            managedVersionMap.put( managementKey, artifact );
        }

        project.setManagedVersionMap( managedVersionMap );
    }
    
    private String getManagementKey( Artifact artifact )
    {
        return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getType()
            + ( artifact.getClassifier() != null ? ":" + artifact.getClassifier() : "" );
    }
    
    private void assertDependencyTree( DependencyNode expectedRootNode, MavenProject project )
        throws DependencyTreeBuilderException
    {
        assertDependencyTree( expectedRootNode, project, null );
    }
    
    private void assertDependencyTree( DependencyNode expectedRootNode, MavenProject project,
                                       ArtifactFilter artifactFilter )
        throws DependencyTreeBuilderException
    {
        // assert built dependency tree is as expected

        DependencyNode actualRootNode =
            builder.buildDependencyTree( project, artifactRepository, artifactFactory, artifactMetadataSource,
                                         artifactFilter, artifactCollector );

        assertEquals( "Dependency tree", expectedRootNode, actualRootNode );

        // assert resolution tree is as expected

        ArtifactResolutionResult result = builder.getArtifactResolutionResult();

        assertTreeEquals( expectedRootNode, project, result );
    }
    
    private void assertTreeEquals( DependencyNode dependencyNode, MavenProject project,
                                   ArtifactResolutionResult resolutionResult )
    {
        List<ResolutionNode> rootChildrenResolutionNodes =
            ResolutionNodeUtils.getRootChildrenResolutionNodes( project, resolutionResult );

        try
        {
            assertEquals( "Root node artifact", dependencyNode.getArtifact(), project.getArtifact() );

            assertNodesEquals( dependencyNode.getChildren(), rootChildrenResolutionNodes );
        }
        catch ( AssertionFailedError error )
        {
            StringBuffer buffer = new StringBuffer();

            buffer.append( error.getMessage() ).append( "; " );
            buffer.append( "expected dependency tree <" ).append( dependencyNode ).append( "> " );
            buffer.append( "actual resolution tree <" );
            ResolutionNodeUtils.append( buffer, project, resolutionResult );
            buffer.append( ">" );

            throw new AssertionFailedError( buffer.toString() );
        }
    }
    
    private void assertNodesEquals( List<DependencyNode> dependencyNodes, List<ResolutionNode> resolutionNodes )
    {
        assertNodesEquals( dependencyNodes.iterator(), resolutionNodes.iterator() );
    }

    private void assertNodesEquals( Iterator<DependencyNode> dependencyNodesIterator,
                                    Iterator<ResolutionNode> resolutionNodesIterator )
    {
        while ( dependencyNodesIterator.hasNext() && resolutionNodesIterator.hasNext() )
        {
            DependencyNode dependencyNode = dependencyNodesIterator.next();
            ResolutionNode resolutionNode = resolutionNodesIterator.next();
            
            assertNodeEquals( dependencyNode, resolutionNode );
        }
        
        if ( dependencyNodesIterator.hasNext() || resolutionNodesIterator.hasNext() )
        {
            fail( "Node list size differs" );
        }
    }

    private void assertNodeEquals( DependencyNode dependencyNode, ResolutionNode resolutionNode )
    {
        assertEquals( "Node state", dependencyNode.getState() == DependencyNode.INCLUDED, resolutionNode.isActive() );
        
        assertEquals( "Node artifact", dependencyNode.getArtifact(), resolutionNode.getArtifact() );
        
        assertNodesEquals( dependencyNode.getChildren().iterator(), resolutionNode.getChildrenIterator() );
    }
    
    private String get( String[] array, int index )
    {
        return get( array, index, null );
    }
    
    private String get( String[] array, int index, String defaultValue )
    {
        return ( index < array.length ) ? array[index] : defaultValue;
    }
}
