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.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;

import org.apache.maven.artifact.Artifact;

/**
 * Tests <code>DependencyNode</code>.
 *  
 * @author <a href="mailto:carlos@apache.org">Carlos Sanchez</a>
 * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
 * @version $Id$
 * @see DependencyNode
 */
public class DependencyNodeTest
    extends AbstractDependencyNodeTest
{
    private DependencyNode rootNode, node1, node2, node3, node4, node5, node6, node7;

    protected void setUp()
        throws Exception
    {
        super.setUp();

        /*
         *     ------1------
         * ----2----       3
         * 4       5       7
         *         6
         */

        node1 = createNode( 1 );
        node2 = createNode( node1, 2 );
        node3 = createNode( node1, 3 );
        node4 = createNode( node2, 4 );
        node5 = createNode( node2, 5 );
        node6 = createNode( node5, 6 );
        node7 = createNode( node3, 7 );

        rootNode = node1;
    }

    private void assertNode( Iterator it, DependencyNode node )
    {
        assertTrue( it.hasNext() );
        assertSame( node, it.next() );
    }

    public void testPreorderIterator()
    {
        Iterator it = rootNode.iterator();

        assertNode( it, node1 );
        assertNode( it, node2 );
        assertNode( it, node4 );
        assertNode( it, node5 );
        assertNode( it, node6 );
        assertNode( it, node3 );
        assertNode( it, node7 );
        assertFalse( it.hasNext() );
    }

    public void testInverseIterator()
    {
        Iterator it = rootNode.inverseIterator();

        assertNode( it, node7 );
        assertNode( it, node3 );
        assertNode( it, node6 );
        assertNode( it, node5 );
        assertNode( it, node4 );
        assertNode( it, node2 );
        assertNode( it, node1 );
        assertFalse( it.hasNext() );
    }
    
    public void testToNodeString()
    {
        assertEquals( "groupId1:artifactId1:jar:1:compile", node1.toNodeString() );
    }

    public void testToString()
        throws Exception
    {
        BufferedReader reader = new BufferedReader( new StringReader( node1.toString() ) );

        assertLine( reader, 1, 0 );
        assertLine( reader, 2, 1 );
        assertLine( reader, 4, 2 );
        assertLine( reader, 5, 2 );
        assertLine( reader, 6, 3 );
        assertLine( reader, 3, 1 );
        assertLine( reader, 7, 2 );
    }
    
    public void testOmitForConflict()
    {
        Artifact relatedArtifact = createArtifact( createArtifactId( 2, "3" ) );
        node2.omitForConflict( relatedArtifact );
        
        assertEquals( DependencyNode.OMITTED_FOR_CONFLICT, node2.getState() );
        assertEquals( relatedArtifact, node2.getRelatedArtifact() );
        
        assertTrue( node2.getChildren().isEmpty() );
        assertNull( node4.getParent() );
        assertNull( node5.getParent() );
    }
    
    public void testOmitForConflictWithDuplicate()
    {
        Artifact relatedArtifact = createArtifact( createArtifactId( 2 ) );
        node2.omitForConflict( relatedArtifact );
        
        assertEquals( DependencyNode.OMITTED_FOR_DUPLICATE, node2.getState() );
        assertEquals( relatedArtifact, node2.getRelatedArtifact() );
        
        assertTrue( node2.getChildren().isEmpty() );
        assertNull( node4.getParent() );
        assertNull( node5.getParent() );
    }

    public void testOmitForCycle()
    {
        node2.omitForCycle();
        
        assertEquals( DependencyNode.OMITTED_FOR_CYCLE, node2.getState() );
        
        assertTrue( node2.getChildren().isEmpty() );
        assertNull( node4.getParent() );
        assertNull( node5.getParent() );
    }
    
    private void assertLine( BufferedReader reader, int i, int depth )
        throws IOException
    {
        String line = reader.readLine();
        StringBuffer sb = new StringBuffer();
        for ( int j = 0; j < depth; j++ )
        {
            sb.append( "   " );
        }
        sb.append( "groupId" );
        sb.append( i );
        sb.append( ":artifactId" );
        sb.append( i );
        sb.append( ":jar:" );
        sb.append( i );
        sb.append( ":compile" );
        assertEquals( sb.toString(), line );
    }

    private DependencyNode createNode( DependencyNode parent, int i )
    {
        DependencyNode node = createNode( i );
        
        parent.addChild( node );
        
        return node;
    }

    private DependencyNode createNode( int i )
    {
        return createNode( createArtifactId( i ) );
    }

    private String createArtifactId( int i )
    {
        return createArtifactId( i, Integer.toString( i ) ); 
    }

    private String createArtifactId( int i, String version )
    {
        return "groupId" + i + ":artifactId" + i + ":jar:" + version + ":compile"; 
    }
}
