1 package org.apache.maven.shared.dependency.tree.traversal;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.PrintWriter;
23 import java.io.Writer;
24 import java.util.List;
25
26 import org.apache.maven.shared.dependency.tree.DependencyNode;
27
28 /**
29 * A dependency node visitor that serializes visited nodes to a writer.
30 *
31 * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
32 * @version $Id: SerializingDependencyNodeVisitor.java 661727 2008-05-30 14:21:49Z bentmann $
33 * @since 1.1
34 */
35 public class SerializingDependencyNodeVisitor implements DependencyNodeVisitor
36 {
37
38
39 /**
40 * Provides tokens to use when serializing the dependency tree.
41 */
42 public static class TreeTokens
43 {
44 private final String nodeIndent;
45
46 private final String lastNodeIndent;
47
48 private final String fillIndent;
49
50 private final String lastFillIndent;
51
52 public TreeTokens( String nodeIndent, String lastNodeIndent, String fillIndent, String lastFillIndent )
53 {
54 this.nodeIndent = nodeIndent;
55 this.lastNodeIndent = lastNodeIndent;
56 this.fillIndent = fillIndent;
57 this.lastFillIndent = lastFillIndent;
58 }
59
60 public String getNodeIndent( boolean last )
61 {
62 return last ? lastNodeIndent : nodeIndent;
63 }
64
65 public String getFillIndent( boolean last )
66 {
67 return last ? lastFillIndent : fillIndent;
68 }
69 }
70
71
72
73 /**
74 * Whitespace tokens to use when outputing the dependency tree.
75 */
76 public static final TreeTokens WHITESPACE_TOKENS = new TreeTokens( " ", " ", " ", " " );
77
78 /**
79 * The standard ASCII tokens to use when outputing the dependency tree.
80 */
81 public static final TreeTokens STANDARD_TOKENS = new TreeTokens( "+- ", "\\- ", "| ", " " );
82
83 /**
84 * The extended ASCII tokens to use when outputing the dependency tree.
85 */
86 public static final TreeTokens EXTENDED_TOKENS =
87 new TreeTokens( "\u00c3\u00c4 ", "\u00c0\u00c4 ", "\u00b3 ", " " );
88
89
90
91 /**
92 * The writer to serialize to.
93 */
94 private final PrintWriter writer;
95
96 /**
97 * The tokens to use when serializing the dependency tree.
98 */
99 private final TreeTokens tokens;
100
101 /**
102 * The depth of the currently visited dependency node.
103 */
104 private int depth;
105
106
107
108 /**
109 * Creates a dependency node visitor that serializes visited nodes to the specified writer using whitespace tokens.
110 *
111 * @param writer
112 * the writer to serialize to
113 */
114 public SerializingDependencyNodeVisitor( Writer writer )
115 {
116 this( writer, WHITESPACE_TOKENS );
117 }
118
119 /**
120 * Creates a dependency node visitor that serializes visited nodes to the specified writer using the specified
121 * tokens.
122 *
123 * @param writer
124 * the writer to serialize to
125 * @param tokens
126 * the tokens to use when serializing the dependency tree
127 */
128 public SerializingDependencyNodeVisitor( Writer writer, TreeTokens tokens )
129 {
130 if ( writer instanceof PrintWriter )
131 {
132 this.writer = (PrintWriter) writer;
133 }
134 else
135 {
136 this.writer = new PrintWriter( writer, true );
137 }
138
139 this.tokens = tokens;
140
141 depth = 0;
142 }
143
144
145
146 /**
147 * {@inheritDoc}
148 */
149 public boolean visit( DependencyNode node )
150 {
151 indent( node );
152
153 writer.println( node.toNodeString() );
154
155 depth++;
156
157 return true;
158 }
159
160 /**
161 * {@inheritDoc}
162 */
163 public boolean endVisit( DependencyNode node )
164 {
165 depth--;
166
167 return true;
168 }
169
170
171
172 /**
173 * Writes the necessary tokens to indent the specified dependency node to this visitor's writer.
174 *
175 * @param node
176 * the dependency node to indent
177 */
178 private void indent( DependencyNode node )
179 {
180 for ( int i = 1; i < depth; i++ )
181 {
182 writer.write( tokens.getFillIndent( isLast( node, i ) ) );
183 }
184
185 if ( depth > 0 )
186 {
187 writer.write( tokens.getNodeIndent( isLast( node ) ) );
188 }
189 }
190
191 /**
192 * Gets whether the specified dependency node is the last of its siblings.
193 *
194 * @param node
195 * the dependency node to check
196 * @return <code>true</code> if the specified dependency node is the last of its last siblings
197 */
198 private boolean isLast( DependencyNode node )
199 {
200
201
202 DependencyNode parent = node.getParent();
203
204 boolean last;
205
206 if ( parent == null )
207 {
208 last = true;
209 }
210 else
211 {
212 List siblings = parent.getChildren();
213
214 last = ( siblings.indexOf( node ) == siblings.size() - 1 );
215 }
216
217 return last;
218 }
219
220 /**
221 * Gets whether the specified dependency node ancestor is the last of its siblings.
222 *
223 * @param node
224 * the dependency node whose ancestor to check
225 * @param ancestorDepth
226 * the depth of the ancestor of the specified dependency node to check
227 * @return <code>true</code> if the specified dependency node ancestor is the last of its siblings
228 */
229 private boolean isLast( DependencyNode node, int ancestorDepth )
230 {
231
232
233 int distance = depth - ancestorDepth;
234
235 while ( distance-- > 0 )
236 {
237 node = node.getParent();
238 }
239
240 return isLast( node );
241 }
242 }