Class PathConflictResolver

  • All Implemented Interfaces:
    org.eclipse.aether.collection.DependencyGraphTransformer

    public final class PathConflictResolver
    extends ConflictResolver
    A dependency graph transformer that resolves version and scope conflicts among dependencies. This resolver builds a cycle-free parallel path tree from the dependency graph, then processes conflict groups in topologically sorted order to select winners.

    For a given set of conflicting nodes, one node will be chosen as the winner. How losing nodes are handled depends on the configured verbosity level: they may be removed entirely, have their children removed, or be left in place with conflict information. The exact rules by which a winning node and its effective scope are determined are controlled by user-supplied implementations of ConflictResolver.VersionSelector, ConflictResolver.ScopeSelector, ConflictResolver.OptionalitySelector and ConflictResolver.ScopeDeriver.

    Algorithm Overview:

    1. Path Tree Construction: Builds a cycle-free parallel tree structure from the input dependency graph, where each Path represents a unique route to a dependency node. To avoid exponential memory use in highly connected graphs, subtree expansion of each DependencyNode instance is bounded: when the same node is reached again via a different parent path, a Path entry is still created for it (so all occurrences appear in the conflict partition), but its subtree is only re-traversed if reached at a strictly shallower depth than before.
    2. Conflict Partitioning: Groups paths by conflict ID (based on groupId:artifactId:classifier:extension coordinates)
    3. Topological Processing: Processes conflict groups in topologically sorted order
    4. Winner Selection: Uses provided selectors to choose winners within each conflict group
    5. Graph Transformation: Applies changes back to the original dependency graph

    Key Differences from ClassicConflictResolver:

    • Memory Strategy: Uses parallel tree structure vs in-place graph modification
    • Cycle Handling: Explicitly breaks cycles during tree construction
    • Processing Order: Level-by-level from root vs depth-first traversal

    Implementation Note: This conflict resolver builds a cycle-free "parallel" structure based on the passed-in dependency graph, and applies operations level by level starting from the root. The parallel Path tree ensures that cycles in the original graph don't affect the conflict resolution algorithm's performance.

    Since:
    2.0.11
    See Also:
    ClassicConflictResolver
    • Field Detail

      • CONFIG_PROP_SHOW_CYCLES_IN_STANDARD_VERBOSITY

        public static final java.lang.String CONFIG_PROP_SHOW_CYCLES_IN_STANDARD_VERBOSITY
        This implementation of conflict resolver is able to show more precise information regarding cycles in standard verbose mode. But, to make it really drop-in-replacement, we "tame down" this information. Still, users needing it may want to enable this for easier cycle detection, but in that case this conflict resolver will provide "extra nodes" not present on "standard verbosity level" with "classic" conflict resolver, that may lead to IT issues down the stream. Hence, the default is to provide as much information as much verbose "classic" does.
        Since:
        2.0.12
        See Also:
        Constant Field Values
    • Method Detail

      • transformGraph

        public org.eclipse.aether.graph.DependencyNode transformGraph​(org.eclipse.aether.graph.DependencyNode node,
                                                                      org.eclipse.aether.collection.DependencyGraphTransformationContext context)
                                                               throws org.eclipse.aether.RepositoryException
        Specified by:
        transformGraph in interface org.eclipse.aether.collection.DependencyGraphTransformer
        Overrides:
        transformGraph in class ConflictResolver
        Throws:
        org.eclipse.aether.RepositoryException