001package org.apache.maven.resolver.examples.util;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.PrintStream;
023import java.util.ArrayList;
024import java.util.Iterator;
025import java.util.List;
026
027import org.eclipse.aether.artifact.Artifact;
028import org.eclipse.aether.graph.Dependency;
029import org.eclipse.aether.graph.DependencyNode;
030import org.eclipse.aether.graph.DependencyVisitor;
031import org.eclipse.aether.util.artifact.ArtifactIdUtils;
032import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
033import org.eclipse.aether.util.graph.transformer.ConflictResolver;
034
035/**
036 * A dependency visitor that dumps the graph to the console.
037 */
038public class ConsoleDependencyGraphDumper
039    implements DependencyVisitor
040{
041
042    private PrintStream out;
043
044    private List<ChildInfo> childInfos = new ArrayList<ChildInfo>();
045
046    public ConsoleDependencyGraphDumper()
047    {
048        this( null );
049    }
050
051    public ConsoleDependencyGraphDumper( PrintStream out )
052    {
053        this.out = ( out != null ) ? out : System.out;
054    }
055
056    public boolean visitEnter( DependencyNode node )
057    {
058        out.println( formatIndentation() + formatNode( node ) );
059        childInfos.add( new ChildInfo( node.getChildren().size() ) );
060        return true;
061    }
062
063    private String formatIndentation()
064    {
065        StringBuilder buffer = new StringBuilder( 128 );
066        for ( Iterator<ChildInfo> it = childInfos.iterator(); it.hasNext(); )
067        {
068            buffer.append( it.next().formatIndentation( !it.hasNext() ) );
069        }
070        return buffer.toString();
071    }
072
073    private String formatNode( DependencyNode node )
074    {
075        StringBuilder buffer = new StringBuilder( 128 );
076        Artifact a = node.getArtifact();
077        Dependency d = node.getDependency();
078        buffer.append( a );
079        if ( d != null && d.getScope().length() > 0 )
080        {
081            buffer.append( " [" ).append( d.getScope() );
082            if ( d.isOptional() )
083            {
084                buffer.append( ", optional" );
085            }
086            buffer.append( "]" );
087        }
088        {
089            String premanaged = DependencyManagerUtils.getPremanagedVersion( node );
090            if ( premanaged != null && !premanaged.equals( a.getBaseVersion() ) )
091            {
092                buffer.append( " (version managed from " ).append( premanaged ).append( ")" );
093            }
094        }
095        {
096            String premanaged = DependencyManagerUtils.getPremanagedScope( node );
097            if ( premanaged != null && !premanaged.equals( d.getScope() ) )
098            {
099                buffer.append( " (scope managed from " ).append( premanaged ).append( ")" );
100            }
101        }
102        DependencyNode winner = (DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER );
103        if ( winner != null && !ArtifactIdUtils.equalsId( a, winner.getArtifact() ) )
104        {
105            Artifact w = winner.getArtifact();
106            buffer.append( " (conflicts with " );
107            if ( ArtifactIdUtils.toVersionlessId( a ).equals( ArtifactIdUtils.toVersionlessId( w ) ) )
108            {
109                buffer.append( w.getVersion() );
110            }
111            else
112            {
113                buffer.append( w );
114            }
115            buffer.append( ")" );
116        }
117        return buffer.toString();
118    }
119
120    public boolean visitLeave( DependencyNode node )
121    {
122        if ( !childInfos.isEmpty() )
123        {
124            childInfos.remove( childInfos.size() - 1 );
125        }
126        if ( !childInfos.isEmpty() )
127        {
128            childInfos.get( childInfos.size() - 1 ).index++;
129        }
130        return true;
131    }
132
133    private static class ChildInfo
134    {
135
136        final int count;
137
138        int index;
139
140        ChildInfo( int count )
141        {
142            this.count = count;
143        }
144
145        public String formatIndentation( boolean end )
146        {
147            boolean last = index + 1 >= count;
148            if ( end )
149            {
150                return last ? "\\- " : "+- ";
151            }
152            return last ? "   " : "|  ";
153        }
154
155    }
156
157}