View Javadoc
1   /*
2   Copyright (C) 2014 Chr. Clemens Lee <clemens@kclee.com>.
3   
4   This file is part of JavaNCSS
5   (http://javancss.codehaus.org/).
6   
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11  
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  Lesser General Public License for more details.
16  
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA*/
20  
21  package javancss;
22  
23  import java.io.IOException;
24  import java.io.Writer;
25  import java.text.DecimalFormat;
26  import java.text.NumberFormat;
27  import java.util.List;
28  import java.util.Locale;
29  
30  /**
31   * Generates ascii output of Java metrics.
32   *
33   * @author    Chr. Clemens Lee <clemens@kclee.com>
34   *            , Windows 13 10 line feed feature by John Wilson.
35   * @version   $Id$
36   */
37  public class AsciiFormatter implements Formatter
38  {
39      private static final int LEN_NR = 3;
40      private static final String NL = System.getProperty( "line.separator" );
41  
42      private final Javancss _javancss;
43  
44      private String[] _header = null;
45      private int      _length = 0;
46      private int      _nr     = 0;
47  
48      private NumberFormat _pNumberFormat = null;
49  
50      private String _formatListHeader( int lines, String[] header )
51      {
52          _header = header;
53  
54          _nr = 0;
55  
56          StringBuilder sRetVal = new StringBuilder();
57  
58          _length = String.valueOf( lines ).length();
59          int spaces = Math.max( 0, _length - LEN_NR );
60          _length = spaces + LEN_NR;
61          sRetVal.append( multiplyChar( ' ', spaces ) );
62          sRetVal.append( "Nr." );
63          for (String h : header)
64          {
65              sRetVal.append(' ').append(h);
66          }
67          sRetVal.append( NL );
68  
69          return sRetVal.toString();
70      }
71  
72      private String _formatListLine( String name, int[] value )
73      {
74          StringBuilder sLine = new StringBuilder();
75  
76          _nr++;
77          sLine.append( pad( String.valueOf( _nr ), _length ) );
78          for( int index = 0; index < _header.length - 1; index++ )
79          {
80              sLine.append( ' ' );
81              sLine.append( pad( String.valueOf( value[index] ), _header[index].length() ) );
82          }
83          sLine.append( ' ' );
84          sLine.append( name );
85          sLine.append( NL );
86  
87          return sLine.toString();
88      }
89  
90      private double _divide( int divident, int divisor )
91      {
92          double dRetVal = 0.0;
93          if ( divisor > 0 )
94          {
95              dRetVal = Math.round( ( (double) divident / (double) divisor ) * 100 ) / 100.0;
96          }
97  
98          return dRetVal;
99      }
100 
101     private double _divide( long divident, long divisor )
102     {
103         double dRetVal = 0.0;
104         if ( divisor > 0 )
105         {
106             dRetVal = Math.round( ( (double) divident / (double) divisor ) * 100 ) / 100.0;
107         }
108 
109         return dRetVal;
110     }
111 
112     private String _formatPackageMatrix( int packages
113                                          , int classesSum
114                                          , int functionsSum
115                                          , int javadocsSum
116                                          , int ncssSum      )
117     {
118         ( (DecimalFormat) _pNumberFormat ).applyPattern( "###0.00" );
119         int maxItemLength = _pNumberFormat.format( ncssSum ).length();
120         maxItemLength = Math.max( 9, maxItemLength );
121         String sRetVal =
122             pad("Packages", maxItemLength) + ' '
123             + pad("Classes", maxItemLength) + ' '
124             + pad("Functions", maxItemLength) + ' '
125             + pad("NCSS", maxItemLength) + ' '
126             + pad("Javadocs", maxItemLength)
127             + " | per" + NL
128 
129             + multiplyChar( '-', ( maxItemLength + 1 ) * 6 + 1 ) + NL
130             + pad( _pNumberFormat.format( packages ), maxItemLength ) + ' '
131             + pad( _pNumberFormat.format( classesSum ), maxItemLength ) + ' '
132             + pad( _pNumberFormat.format( functionsSum ), maxItemLength ) + ' '
133             + pad( _pNumberFormat.format( ncssSum ), maxItemLength ) + ' '
134             + pad( _pNumberFormat.format( javadocsSum ), maxItemLength )
135             + " | Project" + NL
136 
137             + multiplyChar( ' ', maxItemLength + 1 )
138             + pad( _pNumberFormat.format( _divide( classesSum, packages ) ), maxItemLength ) + ' '
139             + pad( _pNumberFormat.format( _divide( functionsSum, packages ) ), maxItemLength ) + ' '
140             + pad( _pNumberFormat.format( _divide( ncssSum, packages ) ), maxItemLength ) + ' '
141             + pad( _pNumberFormat.format( _divide( javadocsSum, packages ) ), maxItemLength )
142             + " | Package" + NL
143 
144             + multiplyChar( ' ', (maxItemLength + 1)*2 )
145             + pad( _pNumberFormat.format( _divide( functionsSum, classesSum ) ), maxItemLength ) + ' '
146             + pad( _pNumberFormat.format( _divide( ncssSum, classesSum ) ), maxItemLength ) + ' '
147             + pad( _pNumberFormat.format( _divide( javadocsSum, classesSum ) ), maxItemLength )
148             + " | Class" + NL
149 
150             + multiplyChar( ' ', (maxItemLength + 1)*3 )
151             + pad( _pNumberFormat.format( _divide( ncssSum, functionsSum ) ), maxItemLength ) + ' '
152             + pad( _pNumberFormat.format( _divide( javadocsSum, functionsSum ) ), maxItemLength )
153             + " | Function" + NL;
154 
155         ((DecimalFormat)_pNumberFormat).applyPattern( "#,##0.00" );
156 
157         return sRetVal;
158     }
159 
160     public AsciiFormatter( Javancss javancss )
161     {
162         _javancss = javancss;
163 
164         _pNumberFormat = NumberFormat.getInstance( Locale.US );
165         ((DecimalFormat)_pNumberFormat).applyPattern( "#,##0.00" );
166     }
167 
168     public void printPackageNcss( Writer w )
169         throws IOException
170     {
171         List<PackageMetric> vPackageMetrics = _javancss.getPackageMetrics();
172 
173         int packages = vPackageMetrics.size();
174 
175         w.write( _formatListHeader( packages
176                                             , new String[] {   "  Classes"
177                                                              , "Functions"
178                                                              , "     NCSS"
179                                                              , " Javadocs"
180                                                              , "Package" } ) );
181 
182         int classesSum   = 0;
183         int functionsSum = 0;
184         int javadocsSum  = 0;
185         int ncssSum      = 0;
186         for( PackageMetric pPackageMetric : vPackageMetrics )
187         {
188             classesSum   += pPackageMetric.classes;
189             functionsSum += pPackageMetric.functions;
190             ncssSum      += pPackageMetric.ncss;
191             javadocsSum  += pPackageMetric.javadocs;
192             w.write( _formatListLine( pPackageMetric.name
193                                         , new int[] { pPackageMetric.classes
194                                                       , pPackageMetric.functions
195                                                       , pPackageMetric.ncss
196                                                       , pPackageMetric.javadocs
197                                         } ) );
198         }
199 
200         int packagesLength = String.valueOf( packages ).length();
201         int spaces = Math.max( packagesLength, LEN_NR ) + 1;
202         w.write( multiplyChar( ' ', spaces ) +
203                "--------- --------- --------- ---------" + NL );
204 
205         w.write( multiplyChar( ' ', spaces )
206                 + String.format( "%9d %9d %9d %9d Total" + NL + NL, classesSum, functionsSum, ncssSum, javadocsSum ) );
207 
208         w.write( _formatPackageMatrix( packages
209                                          , classesSum
210                                          , functionsSum
211                                          , javadocsSum
212                                          , ncssSum      ) );
213     }
214 
215     private String _formatObjectResume( int objects
216                                         , long lObjectSum
217                                         , long lFunctionSum
218                                         , long lClassesSum
219                                         , long lJVDCSum     )
220     {
221         double fAverageNcss     = _divide( lObjectSum  , objects );
222         double fAverageFuncs    = _divide( lFunctionSum, objects );
223         double fAverageClasses  = _divide( lClassesSum , objects );
224         double fAverageJavadocs = _divide( lJVDCSum    , objects );
225         return String.format( Locale.US,
226                   "Average Object NCSS:             %9.2f" + NL
227                 + "Average Object Functions:        %9.2f" + NL
228                 + "Average Object Inner Classes:    %9.2f" + NL
229                 + "Average Object Javadoc Comments: %9.2f" + NL
230                 + "Program NCSS:                    %,9.2f" + NL,
231                 fAverageNcss, fAverageFuncs, fAverageClasses, fAverageJavadocs, (double) _javancss.getNcss() );
232     }
233 
234     public void printObjectNcss( Writer w )
235         throws IOException
236     {
237         List<ObjectMetric> vObjectMetrics = _javancss.getObjectMetrics();
238 
239         w.write( _formatListHeader( vObjectMetrics.size()
240                                             , new String[] { "NCSS"
241                                                              , "Functions"
242                                                              , "Classes"
243                                                              , "Javadocs"
244                                                              , "Class"     } ) );
245         long lFunctionSum = 0;
246         long lClassesSum  = 0;
247         long lObjectSum   = 0;
248         long lJVDCSum     = 0;
249         for ( ObjectMetric classMetric : vObjectMetrics )
250         {
251             String sClass = classMetric.name;
252             int objectNcss = classMetric.ncss;
253             int functions  = classMetric.functions;
254             int classes    = classMetric.classes;
255             int jvdcs      = classMetric.javadocs;
256             lObjectSum   += objectNcss;
257             lFunctionSum += functions;
258             lClassesSum  += classes;
259             lJVDCSum     += jvdcs;
260             w.write( _formatListLine( sClass
261                                         , new int[] { objectNcss
262                                                       , functions
263                                                       , classes
264                                                       , jvdcs     } ) );
265         }
266 
267         w.write( _formatObjectResume( vObjectMetrics.size()
268                                         , lObjectSum
269                                         , lFunctionSum
270                                         , lClassesSum
271                                         , lJVDCSum            ) );
272     }
273 
274     private String _formatFunctionResume( int functions
275                                           , long lFunctionSum
276                                           , long lCCNSum
277                                           , long lJVDCSum     )
278     {
279         double fAverageNcss = _divide( lFunctionSum, functions );
280         double fAverageCCN  = _divide( lCCNSum     , functions );
281         double fAverageJVDC = _divide( lJVDCSum    , functions );
282 
283         return String.format( Locale.US,
284                   "Average Function NCSS: %10.2f" + NL 
285                 + "Average Function CCN:  %10.2f" + NL
286                 + "Average Function JVDC: %10.2f" + NL
287                 + "Program NCSS:          %,10.2f" + NL,
288                 fAverageNcss, fAverageCCN, fAverageJVDC, (double) _javancss.getNcss() );
289     }
290 
291     public void printFunctionNcss( Writer w )
292         throws IOException
293     {
294         List<FunctionMetric> vFunctionMetrics = _javancss.getFunctionMetrics();
295 
296         w.write( _formatListHeader( vFunctionMetrics.size()
297                                            , new String[] { "NCSS"
298                                                             , "CCN"
299                                                             , "JVDC"
300                                                             , "Function" } ) );
301 
302         long lFunctionSum = 0;
303         long lCCNSum      = 0;
304         long lJVDCSum     = 0;
305         for ( FunctionMetric functionMetric : vFunctionMetrics )
306         {
307             String sFunction = functionMetric.name;
308             int functionNcss = functionMetric.ncss;
309             int functionCCN  = functionMetric.ccn;
310             int functionJVDC = functionMetric.javadocs;
311 
312             lFunctionSum += functionNcss;
313             lCCNSum      += functionCCN;
314             lJVDCSum     += functionJVDC;
315             w.write( _formatListLine( sFunction
316                                              , new int[] { functionNcss
317                                                            , functionCCN
318                                                            , functionJVDC } ) );
319         }
320 
321         w.write( _formatFunctionResume( vFunctionMetrics.size()
322                                                , lFunctionSum
323                                                , lCCNSum
324                                                , lJVDCSum              ) );
325     }
326 
327     public void printJavaNcss( Writer w )
328         throws IOException
329     {
330         w.write( "Java NCSS: " + _javancss.getNcss() + NL );
331     }
332 
333     public void printStart( Writer w )
334     {
335     }
336 
337     public void printEnd( Writer w )
338     {
339     }
340 
341     private String multiplyChar( char c, int count )
342     {
343         String s;
344         for ( s = ""; count > 0; --count )
345         {
346             s = s + c;
347         }
348 
349         return s;
350     }
351 
352     private String pad( String s, int count )
353     {
354         String sRetVal = s;
355         if ( sRetVal.length() >= count )
356         {
357             return sRetVal;
358         }
359         else
360         {
361             String sPadding = multiplyChar( ' ', count - sRetVal.length() );
362             sRetVal = sPadding + sRetVal;
363             return sRetVal;
364         }
365     }
366 }