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<>();
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        String premanaged = DependencyManagerUtils.getPremanagedVersion( node );
089        if ( premanaged != null && !premanaged.equals( a.getBaseVersion() ) )
090        {
091            buffer.append( " (version managed from " ).append( premanaged ).append( ")" );
092        }
093
094        premanaged = DependencyManagerUtils.getPremanagedScope( node );
095        if ( premanaged != null && !premanaged.equals( d.getScope() ) )
096        {
097            buffer.append( " (scope managed from " ).append( premanaged ).append( ")" );
098        }
099        DependencyNode winner = (DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER );
100        if ( winner != null && !ArtifactIdUtils.equalsId( a, winner.getArtifact() ) )
101        {
102            Artifact w = winner.getArtifact();
103            buffer.append( " (conflicts with " );
104            if ( ArtifactIdUtils.toVersionlessId( a ).equals( ArtifactIdUtils.toVersionlessId( w ) ) )
105            {
106                buffer.append( w.getVersion() );
107            }
108            else
109            {
110                buffer.append( w );
111            }
112            buffer.append( ")" );
113        }
114        return buffer.toString();
115    }
116
117    public boolean visitLeave( DependencyNode node )
118    {
119        if ( !childInfos.isEmpty() )
120        {
121            childInfos.remove( childInfos.size() - 1 );
122        }
123        if ( !childInfos.isEmpty() )
124        {
125            childInfos.get( childInfos.size() - 1 ).index++;
126        }
127        return true;
128    }
129
130    private static class ChildInfo
131    {
132
133        final int count;
134
135        int index;
136
137        ChildInfo( int count )
138        {
139            this.count = count;
140        }
141
142        public String formatIndentation( boolean end )
143        {
144            boolean last = index + 1 >= count;
145            if ( end )
146            {
147                return last ? "\\- " : "+- ";
148            }
149            return last ? "   " : "|  ";
150        }
151
152    }
153
154}