View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.dependency.tree;
20  
21  import java.io.Writer;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import org.apache.maven.shared.dependency.graph.DependencyNode;
26  import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor;
27  
28  /**
29   * A dependency node visitor that serializes visited nodes to a writer using the
30   * <a href="https://en.wikipedia.org/wiki/Trivial_Graph_Format">TGF format</a>.
31   *
32   * @author <a href="mailto:jerome.creignou@gmail.com">Jerome Creignou</a>
33   * @since 2.1
34   */
35  public class TGFDependencyNodeVisitor extends AbstractSerializingVisitor implements DependencyNodeVisitor {
36  
37      /**
38       * Utiity class to write an Edge.
39       *
40       * @author <a href="mailto:jerome.creignou@gmail.com">Jerome Creignou</a>
41       */
42      static final class EdgeAppender {
43          /**
44           * Edge start.
45           */
46          private final DependencyNode from;
47  
48          /**
49           * Edge end.
50           */
51          private final DependencyNode to;
52  
53          /**
54           * Edge label. (optional)
55           */
56          private final String label;
57  
58          /**
59           * Build a new EdgeAppender.
60           *
61           * @param from edge start.
62           * @param to edge end
63           * @param label optional label.
64           */
65          EdgeAppender(DependencyNode from, DependencyNode to, String label) {
66              super();
67              this.from = from;
68              this.to = to;
69              this.label = label;
70          }
71  
72          /**
73           * build a string representing the edge.
74           */
75          @Override
76          public String toString() {
77              StringBuilder result = new StringBuilder(generateId(from));
78              result.append(' ').append(generateId(to));
79              if (label != null) {
80                  result.append(' ').append(label);
81              }
82              return result.toString();
83          }
84      }
85  
86      /**
87       * List of edges.
88       */
89      private final List<EdgeAppender> edges = new ArrayList<>();
90  
91      /**
92       * Constructor.
93       *
94       * @param writer the writer to write to.
95       */
96      public TGFDependencyNodeVisitor(Writer writer) {
97          super(writer);
98      }
99  
100     /**
101      * {@inheritDoc}
102      */
103     @Override
104     public boolean endVisit(DependencyNode node) {
105         if (node.getParent() == null || node.getParent() == node) {
106             // dump edges on last node endVisit
107             writer.println("#");
108             for (EdgeAppender edge : edges) {
109                 writer.println(edge.toString());
110             }
111         } else {
112             DependencyNode p = node.getParent();
113             // using scope as edge label.
114             edges.add(new EdgeAppender(p, node, node.getArtifact().getScope()));
115         }
116         return true;
117     }
118 
119     /**
120      * {@inheritDoc}
121      */
122     @Override
123     public boolean visit(DependencyNode node) {
124         // write node
125         writer.write(generateId(node));
126         writer.write(" ");
127         writer.println(node.toNodeString());
128         return true;
129     }
130 
131     /**
132      * Generate a unique id from a DependencyNode.
133      * <p>
134      * Current implementation is rather simple and uses hashcode.
135      * </p>
136      *
137      * @param node the DependencyNode to use.
138      * @return the unique id.
139      */
140     private static String generateId(DependencyNode node) {
141         return String.valueOf(node.hashCode());
142     }
143 }