1 package org.apache.maven.plugins.dependency.tree;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.eclipse.aether.graph.DependencyNode;
23
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedList;
27 import java.util.Map;
28 import java.util.Queue;
29 import java.util.Set;
30
31
32
33
34 public class VerboseGraphGraphmlSerializer extends AbstractVerboseGraphSerializer
35 {
36 @Override
37 public String serialize( DependencyNode root )
38 {
39 Set<String> coordinateStrings = new HashSet<>();
40 Map<String, String> coordinateVersionMap = new HashMap<>();
41 Map<DependencyNode, String> nodeErrors = getNodeConflictMessagesBfs( root, coordinateStrings,
42 coordinateVersionMap );
43
44 Set<DependencyNode> visitedNodes = new HashSet<>();
45 Queue<DependencyNode> queue = new LinkedList<>();
46 queue.add( root );
47 StringBuilder result = new StringBuilder( "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
48 + "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" "
49 + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
50 + "xmlns:y=\"http://www.yworks.com/xml/graphml\" "
51 + "xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns "
52 + "http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">"
53 + "\n"
54 + " <key for=\"node\" id=\"d0\" yfiles.type=\"nodegraphics\"/>"
55 + "\n"
56 + " <key for=\"edge\" id=\"d1\" yfiles.type=\"edgegraphics\"/>"
57 + "\n"
58 + "<graph id=\"dependencies\" edgedefault=\"directed\">" + "\n" );
59
60 StringBuilder nodes = new StringBuilder();
61 StringBuilder edges = new StringBuilder();
62 while ( !queue.isEmpty() )
63 {
64 DependencyNode node = queue.poll();
65 nodes.append( getGraphmlNodeLine( node, nodeErrors ) );
66 if ( nodeErrors.get( node ) == null && !node.getArtifact().getProperties().containsKey( "Cycle" ) )
67 {
68 for ( DependencyNode child : node.getChildren() )
69 {
70 if ( !visitedNodes.contains( child ) )
71 {
72 visitedNodes.add( child );
73 queue.add( child );
74 }
75 edges.append( getGraphmlEdgeLine( node, child, nodeErrors ) );
76 }
77 }
78 }
79 result.append( nodes ).append( edges );
80 result.append( "</graph></graphml>" );
81 return result.toString();
82 }
83
84 private String getGraphmlEdgeLine( DependencyNode parent, DependencyNode child,
85 Map<DependencyNode, String> nodeErrors )
86 {
87 StringBuilder builder = new StringBuilder();
88 builder.append( "<edge source=\"" ).append( parent.hashCode() ).append( "\" target=\"" ).append(
89 child.hashCode() ).append( "\"><data key=\"d1\"><y:PolyLineEdge><y:EdgeLabel>" );
90
91
92 boolean messageAdded = false;
93
94 if ( child.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) )
95 {
96 messageAdded = true;
97 builder.append( child.getArtifact().getProperties().get( MANAGED_SCOPE ) );
98 builder.append( ", scope managed from " ).append(
99 child.getArtifact().getProperties().get( PRE_MANAGED_SCOPE ) );
100 }
101 else
102 {
103 builder.append( child.getDependency().getScope() );
104 }
105 if ( child.getArtifact().getProperties().containsKey( "Cycle" ) )
106 {
107 if ( messageAdded )
108 {
109 builder.append( "," );
110 }
111 builder.append( " omitted due to cycle" );
112 }
113 else if ( nodeErrors.get( child ) != null )
114 {
115 if ( messageAdded )
116 {
117 builder.append( "," );
118 }
119 builder.append( " " ).append( nodeErrors.get( child ) );
120 }
121 builder.append( "</y:EdgeLabel></y:PolyLineEdge></data></edge>" ).append( "\n" );
122 return builder.toString();
123 }
124
125 private String getGraphmlNodeLine( DependencyNode node, Map<DependencyNode, String> nodeErrors )
126 {
127 StringBuilder builder = new StringBuilder();
128 builder.append( "<node id=\"" ).append( node.hashCode() ).append(
129 "\"><data key=\"d0\"><y:ShapeNode>" + "<y:NodeLabel>" );
130
131 String coordString = "";
132 boolean messageAdded = false;
133
134 if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_VERSION ) )
135 {
136 coordString +=
137 " - version managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_VERSION );
138 messageAdded = true;
139 }
140 if ( node.getArtifact().getProperties().containsKey( PRE_MANAGED_SCOPE ) )
141 {
142 if ( messageAdded )
143 {
144 coordString += "; ";
145 }
146 else
147 {
148 coordString += " - ";
149 messageAdded = true;
150 }
151 coordString +=
152 "scope managed from " + node.getArtifact().getProperties().get( PRE_MANAGED_SCOPE );
153 }
154 builder.append( getDependencyCoordinate( node ) ).append( coordString );
155 if ( node.getData().containsKey( "ContainsModule" ) )
156 {
157 builder.append( " WARNING: this tree contains a submodule. Once it reaches the submodule will print "
158 + "in nonVerbose fashion, to see the actual submodule "
159 + "verbose output refer to the rest of the output" );
160 }
161 if ( node.getArtifact().getProperties().containsKey( "Cycle" ) )
162 {
163 if ( !messageAdded )
164 {
165 builder.append( " - " );
166 }
167 builder.append( "omitted due to cycle" );
168 }
169 else if ( nodeErrors.get( node ) != null )
170 {
171 if ( !messageAdded )
172 {
173 builder.append( " - " );
174 }
175 builder.append( nodeErrors.get( node ) );
176 }
177 builder.append( "</y:NodeLabel></y:ShapeNode></data></node>" ).append( "\n" );
178 return builder.toString();
179 }
180 }