View Javadoc

1   package org.apache.maven.shared.dependency.tree.traversal;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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      // classes ----------------------------------------------------------------
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      // constants --------------------------------------------------------------
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      // fields -----------------------------------------------------------------
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     // constructors -----------------------------------------------------------
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     // DependencyNodeVisitor methods ------------------------------------------
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     // private methods --------------------------------------------------------
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         // TODO: remove node argument and calculate from visitor calls only
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         // TODO: remove node argument and calculate from visitor calls only
232         
233         int distance = depth - ancestorDepth;
234 
235         while ( distance-- > 0 )
236         {
237             node = node.getParent();
238         }
239 
240         return isLast( node );
241     }
242 }