All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.realityforge.bazel.depgen.DependencyGraphEmitter Maven / Gradle / Ivy

Go to download

bazel-depgen: Generate Bazel dependency scripts by traversing Maven repositories

There is a newer version: 0.19
Show newest version
package org.realityforge.bazel.depgen;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.graph.DependencyVisitor;
import org.eclipse.aether.util.artifact.ArtifactIdUtils;
import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
import org.eclipse.aether.util.graph.transformer.ConflictResolver;
import org.realityforge.bazel.depgen.model.ApplicationModel;
import org.realityforge.bazel.depgen.model.ReplacementModel;

/**
 * A dependency visitor that emits the graph in a format based on Mavens output.
 */
public final class DependencyGraphEmitter
  implements DependencyVisitor
{
  @FunctionalInterface
  public interface LineEmitterFn
  {
    void emitLine( @Nonnull String line );
  }

  @Nonnull
  private final ApplicationModel _model;
  @Nonnull
  private final LineEmitterFn _emitter;
  @Nonnull
  private final List _childInfos = new ArrayList<>();

  public DependencyGraphEmitter( @Nonnull final ApplicationModel model, @Nonnull final LineEmitterFn emitter )
  {
    _model = Objects.requireNonNull( model );
    _emitter = Objects.requireNonNull( emitter );
  }

  @Override
  public boolean visitEnter( @Nonnull final DependencyNode node )
  {
    if ( isSystemArtifact( node ) )
    {
      return false;
    }
    else
    {
      final String line = formatIndentation() + formatNode( node );
      if ( !line.isEmpty() )
      {
        _emitter.emitLine( line );
      }
      final int size =
        (int) node.getChildren().stream().filter( a -> !isSystemArtifact( a ) ).count();
      _childInfos.add( new ChildInfo( size ) );
      return true;
    }
  }

  private boolean isSystemArtifact( @Nonnull final DependencyNode node )
  {
    final Dependency dependency = node.getDependency();
    if ( null != dependency && _model.isSystemArtifact( dependency.getArtifact().getGroupId(),
                                                        dependency.getArtifact().getArtifactId() ) )
    {
      return true;
    }
    else
    {
      final Artifact artifact = node.getArtifact();
      return null != artifact && _model.isSystemArtifact( artifact.getGroupId(), artifact.getArtifactId() );
    }
  }

  @Nonnull
  private String formatIndentation()
  {
    final StringBuilder buffer = new StringBuilder( 128 );
    for ( final Iterator it = _childInfos.iterator(); it.hasNext(); )
    {
      buffer.append( it.next().formatIndentation( !it.hasNext() ) );
    }
    return buffer.toString();
  }

  @Nonnull
  private String formatNode( @Nonnull final DependencyNode node )
  {
    final StringBuilder buffer = new StringBuilder( 128 );
    final Artifact a = node.getArtifact();
    final Dependency d = node.getDependency();
    if ( null != a )
    {
      buffer.append( a );
    }
    if ( null != d && d.getScope().length() > 0 )
    {
      buffer.append( " [" ).append( d.getScope() );
      if ( d.isOptional() )
      {
        buffer.append( ", optional" );
      }
      buffer.append( "]" );
    }
    {
      final String premanaged = DependencyManagerUtils.getPremanagedVersion( node );
      if ( null != premanaged && null != a && !premanaged.equals( a.getBaseVersion() ) )
      {
        buffer.append( " (version managed from " ).append( premanaged ).append( ")" );
      }
    }
    {
      final String premanaged = DependencyManagerUtils.getPremanagedScope( node );
      if ( null != premanaged && null != d && !premanaged.equals( d.getScope() ) )
      {
        buffer.append( " (scope managed from " ).append( premanaged ).append( ")" );
      }
    }
    final DependencyNode winner = (DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER );
    if ( winner != null && !ArtifactIdUtils.equalsId( a, winner.getArtifact() ) )
    {
      final Artifact w = winner.getArtifact();
      buffer.append( " (conflicts with " );
      assert null != a;
      if ( ArtifactIdUtils.toVersionlessId( a ).equals( ArtifactIdUtils.toVersionlessId( w ) ) )
      {
        buffer.append( w.getVersion() );
      }
      else
      {
        buffer.append( w );
      }
      buffer.append( ")" );
    }
    final ReplacementModel replacementModel =
      null != d ? _model.findReplacement( d.getArtifact().getGroupId(), d.getArtifact().getArtifactId() ) : null;
    if ( null != replacementModel )
    {
      buffer.append( " REPLACED BY " );
      buffer.append( replacementModel.getTargets()
                       .stream()
                       .map( t -> t.getTarget() + " (" + t.getNature() + ")" )
                       .collect( Collectors.joining( ", " ) ) );
    }
    return buffer.toString();
  }

  @Override
  public boolean visitLeave( @Nonnull final DependencyNode node )
  {
    if ( !_childInfos.isEmpty() )
    {
      _childInfos.remove( _childInfos.size() - 1 );
    }
    if ( !_childInfos.isEmpty() )
    {
      _childInfos.get( _childInfos.size() - 1 )._index++;
    }
    return true;
  }

  private static class ChildInfo
  {
    final int _count;
    int _index;

    ChildInfo( final int count )
    {
      _count = count;
    }

    String formatIndentation( final boolean end )
    {
      final boolean last = _index + 1 >= _count;
      if ( end )
      {
        return last ? "\\- " : "+- ";
      }
      else
      {
        return last ? "   " : "|  ";
      }
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy