1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.repository.metadata;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.TreeSet;
26 import org.apache.maven.artifact.ArtifactScopeEnum;
27
28
29
30
31
32
33
34 public class MetadataGraph {
35 public static final int DEFAULT_VERTICES = 32;
36 public static final int DEFAULT_EDGES = 64;
37
38
39 private boolean versionedVertices = false;
40 private boolean scopedVertices = false;
41
42
43
44 MetadataGraphVertex entry;
45
46
47 TreeSet<MetadataGraphVertex> vertices;
48
49
50
51
52 Map<MetadataGraphVertex, List<MetadataGraphEdge>> incidentEdges;
53
54 Map<MetadataGraphVertex, List<MetadataGraphEdge>> excidentEdges;
55
56
57
58
59
60 ArtifactScopeEnum scope;
61
62
63
64
65
66 public MetadataGraph(int nVertices) {
67 init(nVertices, 2 * nVertices);
68 }
69
70 public MetadataGraph(int nVertices, int nEdges) {
71 init(nVertices, nEdges);
72 }
73
74
75
76
77 public MetadataGraph(MetadataGraphVertex entry) throws MetadataResolutionException {
78 checkVertex(entry);
79 checkVertices(1);
80
81 entry.setCompareVersion(versionedVertices);
82 entry.setCompareScope(scopedVertices);
83
84 vertices.add(entry);
85 this.entry = entry;
86 }
87
88
89
90
91 public MetadataGraph(MetadataTreeNode tree) throws MetadataResolutionException {
92 this(tree, false, false);
93 }
94
95
96
97
98
99
100
101
102
103
104 public MetadataGraph(MetadataTreeNode tree, boolean versionedVertices, boolean scopedVertices)
105 throws MetadataResolutionException {
106 if (tree == null) {
107 throw new MetadataResolutionException("tree is null");
108 }
109
110 setVersionedVertices(versionedVertices);
111 setScopedVertices(scopedVertices);
112
113 this.versionedVertices = scopedVertices || versionedVertices;
114 this.scopedVertices = scopedVertices;
115
116 int count = countNodes(tree);
117
118 init(count, count + (count / 2));
119
120 processTreeNodes(null, tree, 0, 0);
121 }
122
123 private void processTreeNodes(MetadataGraphVertex parentVertex, MetadataTreeNode node, int depth, int pomOrder)
124 throws MetadataResolutionException {
125 if (node == null) {
126 return;
127 }
128
129 MetadataGraphVertex vertex = new MetadataGraphVertex(node.md, versionedVertices, scopedVertices);
130 if (!vertices.contains(vertex)) {
131 vertices.add(vertex);
132 }
133
134 if (parentVertex != null)
135 {
136 ArtifactMetadata md = node.getMd();
137 MetadataGraphEdge e =
138 new MetadataGraphEdge(md.version, md.resolved, md.artifactScope, md.artifactUri, depth, pomOrder);
139 addEdge(parentVertex, vertex, e);
140 } else {
141 entry = vertex;
142 }
143
144 MetadataTreeNode[] kids = node.getChildren();
145 if (kids == null || kids.length < 1) {
146 return;
147 }
148
149 for (int i = 0; i < kids.length; i++) {
150 MetadataTreeNode n = kids[i];
151 processTreeNodes(vertex, n, depth + 1, i);
152 }
153 }
154
155 public MetadataGraphVertex findVertex(ArtifactMetadata md) {
156 if (md == null || vertices == null || vertices.size() < 1) {
157 return null;
158 }
159
160 MetadataGraphVertex v = new MetadataGraphVertex(md);
161 v.setCompareVersion(versionedVertices);
162 v.setCompareScope(scopedVertices);
163
164 for (MetadataGraphVertex gv : vertices) {
165 if (gv.equals(v)) {
166 return gv;
167 }
168 }
169
170 return null;
171 }
172
173 public MetadataGraphVertex addVertex(ArtifactMetadata md) {
174 if (md == null) {
175 return null;
176 }
177
178 checkVertices();
179
180 MetadataGraphVertex v = findVertex(md);
181 if (v != null) {
182 return v;
183 }
184
185 v = new MetadataGraphVertex(md);
186
187 v.setCompareVersion(versionedVertices);
188 v.setCompareScope(scopedVertices);
189
190 vertices.add(v);
191 return v;
192 }
193
194
195
196
197 private void init(int nVertices, int nEdges) {
198 int nV = nVertices;
199 if (nVertices < 1) {
200 nV = 1;
201 }
202
203 checkVertices(nV);
204
205 int nE = nVertices;
206 if (nEdges <= nV) {
207 nE = 2 * nE;
208 }
209
210 checkEdges(nE);
211 }
212
213 private void checkVertices() {
214 checkVertices(DEFAULT_VERTICES);
215 }
216
217 private void checkVertices(int nVertices) {
218 if (vertices == null) {
219 vertices = new TreeSet<>();
220 }
221 }
222
223 private void checkEdges() {
224 int count = DEFAULT_EDGES;
225
226 if (vertices != null) {
227 count = vertices.size() + vertices.size() / 2;
228 }
229
230 checkEdges(count);
231 }
232
233 private void checkEdges(int nEdges) {
234 if (incidentEdges == null) {
235 incidentEdges = new HashMap<>(nEdges);
236 }
237 if (excidentEdges == null) {
238 excidentEdges = new HashMap<>(nEdges);
239 }
240 }
241
242 private static void checkVertex(MetadataGraphVertex v) throws MetadataResolutionException {
243 if (v == null) {
244 throw new MetadataResolutionException("null vertex");
245 }
246 if (v.getMd() == null) {
247 throw new MetadataResolutionException("vertex without metadata");
248 }
249 }
250
251 private static void checkEdge(MetadataGraphEdge e) throws MetadataResolutionException {
252 if (e == null) {
253 throw new MetadataResolutionException("badly formed edge");
254 }
255 }
256
257 public List<MetadataGraphEdge> getEdgesBetween(MetadataGraphVertex vFrom, MetadataGraphVertex vTo) {
258 List<MetadataGraphEdge> edges = getIncidentEdges(vTo);
259 if (edges == null || edges.isEmpty()) {
260 return null;
261 }
262
263 List<MetadataGraphEdge> res = new ArrayList<>(edges.size());
264
265 for (MetadataGraphEdge e : edges) {
266 if (e.getSource().equals(vFrom)) {
267 res.add(e);
268 }
269 }
270
271 return res;
272 }
273
274 public MetadataGraph addEdge(MetadataGraphVertex vFrom, MetadataGraphVertex vTo, MetadataGraphEdge e)
275 throws MetadataResolutionException {
276 checkVertex(vFrom);
277 checkVertex(vTo);
278
279 checkVertices();
280
281 checkEdge(e);
282 checkEdges();
283
284 e.setSource(vFrom);
285 e.setTarget(vTo);
286
287 vFrom.setCompareVersion(versionedVertices);
288 vFrom.setCompareScope(scopedVertices);
289
290 List<MetadataGraphEdge> exList = excidentEdges.computeIfAbsent(vFrom, k -> new ArrayList<>());
291
292 if (!exList.contains(e)) {
293 exList.add(e);
294 }
295
296 List<MetadataGraphEdge> inList = incidentEdges.computeIfAbsent(vTo, k -> new ArrayList<>());
297
298 if (!inList.contains(e)) {
299 inList.add(e);
300 }
301
302 return this;
303 }
304
305 public MetadataGraph removeVertex(MetadataGraphVertex v) {
306 if (vertices != null && v != null) {
307 vertices.remove(v);
308 }
309
310 if (incidentEdges != null) {
311 incidentEdges.remove(v);
312 }
313
314 if (excidentEdges != null) {
315 excidentEdges.remove(v);
316 }
317
318 return this;
319 }
320
321 private static int countNodes(MetadataTreeNode tree) {
322 if (tree == null) {
323 return 0;
324 }
325
326 int count = 1;
327 MetadataTreeNode[] kids = tree.getChildren();
328 if (kids == null || kids.length < 1) {
329 return count;
330 }
331 for (MetadataTreeNode n : kids) {
332 count += countNodes(n);
333 }
334
335 return count;
336 }
337
338
339 public MetadataGraphVertex getEntry() {
340 return entry;
341 }
342
343 public void setEntry(MetadataGraphVertex entry) {
344 this.entry = entry;
345 }
346
347 public TreeSet<MetadataGraphVertex> getVertices() {
348 return vertices;
349 }
350
351 public List<MetadataGraphEdge> getIncidentEdges(MetadataGraphVertex vertex) {
352 checkEdges();
353 return incidentEdges.get(vertex);
354 }
355
356 public List<MetadataGraphEdge> getExcidentEdges(MetadataGraphVertex vertex) {
357 checkEdges();
358 return excidentEdges.get(vertex);
359 }
360
361 public boolean isVersionedVertices() {
362 return versionedVertices;
363 }
364
365 public void setVersionedVertices(boolean versionedVertices) {
366 this.versionedVertices = versionedVertices;
367 }
368
369 public boolean isScopedVertices() {
370 return scopedVertices;
371 }
372
373 public void setScopedVertices(boolean scopedVertices) {
374 this.scopedVertices = scopedVertices;
375
376
377 if (scopedVertices) {
378 versionedVertices = true;
379 }
380 }
381
382 public ArtifactScopeEnum getScope() {
383 return scope;
384 }
385
386 public void setScope(ArtifactScopeEnum scope) {
387 this.scope = scope;
388 }
389
390
391 public boolean isEmpty() {
392 return entry == null || vertices == null || vertices.isEmpty();
393 }
394
395
396 public boolean isEmptyEdges() {
397 return isEmpty() || incidentEdges == null || incidentEdges.isEmpty();
398 }
399
400 @Override
401 public String toString() {
402 StringBuilder sb = new StringBuilder(512);
403 if (isEmpty()) {
404 return "empty";
405 }
406 for (MetadataGraphVertex v : vertices) {
407 sb.append("Vertex: ").append(v.getMd().toString()).append('\n');
408 List<MetadataGraphEdge> ins = getIncidentEdges(v);
409 if (ins != null) {
410 for (MetadataGraphEdge e : ins) {
411 sb.append(" from : ").append(e.toString()).append('\n');
412 }
413 } else {
414 sb.append(" no entries\n");
415 }
416
417 List<MetadataGraphEdge> outs = getExcidentEdges(v);
418 if (outs != null) {
419 for (MetadataGraphEdge e : outs) {
420 sb.append(" to : ").append(e.toString()).append('\n');
421 }
422 } else {
423 sb.append(" no exit\n");
424 }
425
426 sb.append("-------------------------------------------------\n");
427 }
428 sb.append("=============================================================\n");
429 return sb.toString();
430 }
431
432
433
434 }