1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.aether.util.graph.visitor;
20
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.function.Consumer;
25
26 import org.eclipse.aether.artifact.Artifact;
27 import org.eclipse.aether.graph.Dependency;
28 import org.eclipse.aether.graph.DependencyNode;
29 import org.eclipse.aether.graph.DependencyVisitor;
30 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
31 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
32 import org.eclipse.aether.util.graph.transformer.ConflictResolver;
33
34 import static java.util.Objects.requireNonNull;
35
36
37
38
39
40
41
42 public class DependencyGraphDumper implements DependencyVisitor {
43
44 private final Consumer<String> consumer;
45
46 private final List<ChildInfo> childInfos = new ArrayList<>();
47
48 public DependencyGraphDumper(Consumer<String> consumer) {
49 this.consumer = requireNonNull(consumer);
50 }
51
52 @Override
53 public boolean visitEnter(DependencyNode node) {
54 consumer.accept(formatIndentation() + formatNode(node));
55 childInfos.add(new ChildInfo(node.getChildren().size()));
56 return true;
57 }
58
59 private String formatIndentation() {
60 StringBuilder buffer = new StringBuilder(128);
61 for (Iterator<ChildInfo> it = childInfos.iterator(); it.hasNext(); ) {
62 buffer.append(it.next().formatIndentation(!it.hasNext()));
63 }
64 return buffer.toString();
65 }
66
67 private String formatNode(DependencyNode node) {
68 StringBuilder buffer = new StringBuilder(128);
69 Artifact a = node.getArtifact();
70 Dependency d = node.getDependency();
71 buffer.append(a);
72 if (d != null && !d.getScope().isEmpty()) {
73 buffer.append(" [").append(d.getScope());
74 if (d.isOptional()) {
75 buffer.append(", optional");
76 }
77 buffer.append("]");
78 }
79 String premanaged = DependencyManagerUtils.getPremanagedVersion(node);
80 if (premanaged != null && !premanaged.equals(a.getBaseVersion())) {
81 buffer.append(" (version managed from ").append(premanaged).append(")");
82 }
83
84 premanaged = DependencyManagerUtils.getPremanagedScope(node);
85 if (premanaged != null && d != null && !premanaged.equals(d.getScope())) {
86 buffer.append(" (scope managed from ").append(premanaged).append(")");
87 }
88 DependencyNode winner = (DependencyNode) node.getData().get(ConflictResolver.NODE_DATA_WINNER);
89 if (winner != null) {
90 if (ArtifactIdUtils.equalsId(a, winner.getArtifact())) {
91 buffer.append(" (nearer exists)");
92 } else {
93 Artifact w = winner.getArtifact();
94 buffer.append(" (conflicts with ");
95 if (ArtifactIdUtils.toVersionlessId(a).equals(ArtifactIdUtils.toVersionlessId(w))) {
96 buffer.append(w.getVersion());
97 } else {
98 buffer.append(w);
99 }
100 buffer.append(")");
101 }
102 }
103 return buffer.toString();
104 }
105
106 @Override
107 public boolean visitLeave(DependencyNode node) {
108 if (!childInfos.isEmpty()) {
109 childInfos.remove(childInfos.size() - 1);
110 }
111 if (!childInfos.isEmpty()) {
112 childInfos.get(childInfos.size() - 1).index++;
113 }
114 return true;
115 }
116
117 private static class ChildInfo {
118
119 final int count;
120
121 int index;
122
123 ChildInfo(int count) {
124 this.count = count;
125 }
126
127 public String formatIndentation(boolean end) {
128 boolean last = index + 1 >= count;
129 if (end) {
130 return last ? "\\- " : "+- ";
131 }
132 return last ? " " : "| ";
133 }
134 }
135 }