001    /*
002    Copyright (C) 2001 Chr. Clemens Lee <clemens@kclee.com>.
003    
004    This file is part of JavaNCSS
005    (http://www.kclee.com/clemens/java/javancss/).
006    
007    JavaNCSS is free software; you can redistribute it and/or modify it
008    under the terms of the GNU General Public License as published by the
009    Free Software Foundation; either version 2, or (at your option) any
010    later version.
011    
012    JavaNCSS is distributed in the hope that it will be useful, but WITHOUT
013    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
015    for more details.
016    
017    You should have received a copy of the GNU General Public License
018    along with JavaNCSS; see the file COPYING.  If not, write to
019    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
020    Boston, MA 02111-1307, USA.  */
021    
022    package javancss;
023    
024    import java.text.DecimalFormat;
025    import java.text.NumberFormat;
026    import java.util.Iterator;
027    import java.util.List;
028    import java.util.Locale;
029    
030    import ccl.util.Util;
031    
032    /**
033     * Generates ascii output of Java metrics.
034     *
035     * @author    Chr. Clemens Lee <clemens@kclee.com>
036     *            , Windows 13 10 line feed feature by John Wilson.
037     * @version   $Id: AsciiFormatter.java 121 2009-01-17 22:19:45Z hboutemy $
038     */
039    public class AsciiFormatter implements Formatter
040    {
041        private static final int LEN_NR = 3;
042        private static final String NL = System.getProperty( "line.separator" );
043    
044        private final Javancss _javancss;
045    
046        private String[] _header = null;
047        private int      _length = 0;
048        private int      _nr     = 0;
049    
050        private NumberFormat _pNumberFormat = null;
051    
052        private String _formatListHeader( int lines, String[] header )
053        {
054            _header = header;
055    
056            _nr = 0;
057    
058            StringBuffer sRetVal = new StringBuffer();
059    
060            _length = Util.itoa( lines ).length();
061            int spaces = Math.max( 0, _length - LEN_NR );
062            _length = spaces + LEN_NR;
063            sRetVal.append( Util.multiplyChar(' ', spaces) );
064            sRetVal.append( "Nr." );
065            for( int nr = 0; nr < header.length; nr++ )
066            {
067                sRetVal.append( ' ' ).append( header[ nr ] );
068            }
069            sRetVal.append( NL );
070    
071            return sRetVal.toString();
072        }
073    
074        private String _formatListLine( String name, int[] value )
075        {
076            StringBuffer sLine = new StringBuffer();
077    
078            _nr++;
079            sLine.append( Util.paddWithSpace( _nr, _length ) );
080            for( int index = 0; index < _header.length - 1; index++ )
081            {
082                sLine.append( ' ' );
083                sLine.append( Util.paddWithSpace( value[ index ]
084                                                  , _header[ index ].length() ) );
085            }
086            sLine.append( ' ' );
087            sLine.append( name );
088            sLine.append( NL );
089    
090            return sLine.toString();
091        }
092    
093        private double _divide( int divident, int divisor )
094        {
095            double dRetVal = 0.0;
096            if ( divisor > 0) {
097                dRetVal = Math.round(((double)divident/(double)divisor)*100)/100.0;
098            }
099    
100            return dRetVal;
101        }
102    
103        private double _divide( long divident, long divisor )
104        {
105            double dRetVal = 0.0;
106            if ( divisor > 0) {
107                dRetVal = Math.round(((double)divident/(double)divisor)*100)/100.0;
108            }
109    
110            return dRetVal;
111        }
112    
113        private String _formatPackageMatrix( int packages
114                                             , int classesSum
115                                             , int functionsSum
116                                             , int javadocsSum
117                                             , int ncssSum      )
118        {
119            ((DecimalFormat)_pNumberFormat).applyPattern( "###0.00" );
120            int maxItemLength = _pNumberFormat.format(ncssSum).length();
121            maxItemLength = Math.max(9, maxItemLength);
122            String sRetVal =
123                Util.paddWithSpace( "Packages" , maxItemLength ) + ' '
124                + Util.paddWithSpace("Classes", maxItemLength) + ' '
125                + Util.paddWithSpace("Functions", maxItemLength) + ' '
126                + Util.paddWithSpace("NCSS", maxItemLength) + ' '
127                + Util.paddWithSpace("Javadocs", maxItemLength)
128                + " | per" + NL
129    
130                + Util.multiplyChar( '-', (maxItemLength + 1)*6 + 1 ) + NL
131                + Util.paddWithSpace(_pNumberFormat.format(packages), maxItemLength) + ' '
132                + Util.paddWithSpace(_pNumberFormat.format(classesSum), maxItemLength) + ' '
133                + Util.paddWithSpace(_pNumberFormat.format(functionsSum), maxItemLength) + ' '
134                + Util.paddWithSpace(_pNumberFormat.format(ncssSum), maxItemLength) + ' '
135                + Util.paddWithSpace(_pNumberFormat.format(javadocsSum), maxItemLength)
136                + " | Project" + NL
137    
138                + Util.multiplyChar( ' ', maxItemLength + 1 )
139                + Util.paddWithSpace( _pNumberFormat.format( _divide( classesSum, packages ) ), maxItemLength ) + ' '
140                + Util.paddWithSpace( _pNumberFormat.format( _divide( functionsSum, packages ) ), maxItemLength ) + ' '
141                + Util.paddWithSpace( _pNumberFormat.format( _divide( ncssSum, packages ) ), maxItemLength ) + ' '
142                + Util.paddWithSpace( _pNumberFormat.format( _divide( javadocsSum, packages ) ), maxItemLength )
143                + " | Package" + NL
144    
145                + Util.multiplyChar( ' ', (maxItemLength + 1)*2 )
146                + Util.paddWithSpace( _pNumberFormat.format( _divide( functionsSum, classesSum ) ), maxItemLength ) + ' '
147                + Util.paddWithSpace( _pNumberFormat.format( _divide( ncssSum, classesSum ) ), maxItemLength ) + ' '
148                + Util.paddWithSpace( _pNumberFormat.format( _divide( javadocsSum, classesSum ) ), maxItemLength )
149                + " | Class" + NL
150    
151                + Util.multiplyChar( ' ', (maxItemLength + 1)*3 )
152                + Util.paddWithSpace( _pNumberFormat.format( _divide( ncssSum, functionsSum ) ), maxItemLength ) + ' '
153                + Util.paddWithSpace( _pNumberFormat.format( _divide( javadocsSum, functionsSum ) ), maxItemLength )
154                + " | Function" + NL;
155    
156            ((DecimalFormat)_pNumberFormat).applyPattern( "#,##0.00" );
157    
158            return sRetVal;
159        }
160    
161        public AsciiFormatter( Javancss javancss )
162        {
163            super();
164    
165            _javancss = javancss;
166    
167            _pNumberFormat = NumberFormat.getInstance( Locale.US );
168            ((DecimalFormat)_pNumberFormat).applyPattern( "#,##0.00" );
169        }
170    
171        public String printPackageNcss()
172        {
173            List vPackageMetrics = _javancss.getPackageMetrics();
174    
175            int packages = vPackageMetrics.size();
176    
177            StringBuffer sbRetVal = new StringBuffer( _formatListHeader( packages
178                                                , new String[] {   "  Classes"
179                                                                 , "Functions"
180                                                                 , "     NCSS"
181                                                                 , " Javadocs"
182                                                                 , "Package" } ) );
183    
184            int classesSum   = 0;
185            int functionsSum = 0;
186            int javadocsSum  = 0;
187            int ncssSum      = 0;
188            for( Iterator ePackages = vPackageMetrics.iterator(); ePackages.hasNext(); )
189            {
190                PackageMetric pPackageMetric = (PackageMetric)ePackages.next();
191    
192                classesSum   += pPackageMetric.classes;
193                functionsSum += pPackageMetric.functions;
194                ncssSum      += pPackageMetric.ncss;
195                javadocsSum  += pPackageMetric.javadocs;
196                sbRetVal.append( _formatListLine( pPackageMetric.name
197                                            , new int[] { pPackageMetric.classes
198                                                          , pPackageMetric.functions
199                                                          , pPackageMetric.ncss
200                                                          , pPackageMetric.javadocs
201                                            } ) );
202            }
203    
204            int packagesLength = Util.itoa( packages ).length();
205            int spaces = Math.max( packagesLength, LEN_NR ) + 1;
206            sbRetVal.append( Util.multiplyChar(' ', spaces ) +
207                   "--------- --------- --------- ---------" + NL );
208    
209            sbRetVal.append( Util.multiplyChar(' ', spaces )
210                + Util.paddWithSpace( classesSum, 9 ) + ' '
211                + Util.paddWithSpace( functionsSum, 9 ) + ' '
212                + Util.paddWithSpace( ncssSum, 9 ) + ' '
213                + Util.paddWithSpace( javadocsSum, 9 )
214                + " Total" + NL + NL );
215    
216            sbRetVal.append( _formatPackageMatrix( packages
217                                             , classesSum
218                                             , functionsSum
219                                             , javadocsSum
220                                             , ncssSum      ) );
221    
222            return sbRetVal.toString();
223        }
224    
225        private String _formatObjectResume( int objects
226                                            , long lObjectSum
227                                            , long lFunctionSum
228                                            , long lClassesSum
229                                            , long lJVDCSum     )
230        {
231            double fAverageNcss     = _divide( lObjectSum  , objects );
232            double fAverageFuncs    = _divide( lFunctionSum, objects );
233            double fAverageClasses  = _divide( lClassesSum , objects );
234            double fAverageJavadocs = _divide( lJVDCSum    , objects );
235            String sRetVal = "Average Object NCSS:             "
236                + Util.paddWithSpace(_pNumberFormat.format(fAverageNcss),     9) + NL
237                + "Average Object Functions:        "
238                + Util.paddWithSpace(_pNumberFormat.format(fAverageFuncs),    9) + NL
239                + "Average Object Inner Classes:    "
240                + Util.paddWithSpace(_pNumberFormat.format(fAverageClasses),  9) + NL
241                + "Average Object Javadoc Comments: "
242                + Util.paddWithSpace(_pNumberFormat.format(fAverageJavadocs), 9) + NL
243                + "Program NCSS:                    "
244                + Util.paddWithSpace(_pNumberFormat.format(_javancss.getNcss()), 9) + NL;
245    
246            return sRetVal;
247        }
248    
249        public String printObjectNcss() {
250            List/*<ObjectMetric>*/ vObjectMetrics = _javancss.getObjectMetrics();
251    
252            StringBuffer sbRetVal = new StringBuffer( _formatListHeader( vObjectMetrics.size()
253                                                , new String[] { "NCSS"
254                                                                 , "Functions"
255                                                                 , "Classes"
256                                                                 , "Javadocs"
257                                                                 , "Class"     } ) );
258            long lFunctionSum = 0;
259            long lClassesSum  = 0;
260            long lObjectSum   = 0;
261            long lJVDCSum     = 0;
262            for( Iterator eClasses = vObjectMetrics.iterator(); eClasses.hasNext(); )
263            {
264                ObjectMetric classMetric = (ObjectMetric)eClasses.next();
265                String sClass = classMetric.name;
266                int objectNcss = classMetric.ncss;
267                int functions  = classMetric.functions;
268                int classes    = classMetric.classes;
269                int jvdcs      = classMetric.javadocs;
270                lObjectSum   += (long)objectNcss;
271                lFunctionSum += (long)functions;
272                lClassesSum  += (long)classes;
273                lJVDCSum     += (long)jvdcs;
274                sbRetVal.append( _formatListLine( sClass
275                                            , new int[] { objectNcss
276                                                          , functions
277                                                          , classes
278                                                          , jvdcs     } ) );
279            }
280    
281            sbRetVal.append( _formatObjectResume( vObjectMetrics.size()
282                                            , lObjectSum
283                                            , lFunctionSum
284                                            , lClassesSum
285                                            , lJVDCSum            ) );
286    
287            return sbRetVal.toString();
288        }
289    
290        private String _formatFunctionResume( int functions
291                                              , long lFunctionSum
292                                              , long lCCNSum
293                                              , long lJVDCSum     )
294        {
295            double fAverageNcss = _divide( lFunctionSum, functions );
296            double fAverageCCN  = _divide( lCCNSum     , functions );
297            double fAverageJVDC = _divide( lJVDCSum    , functions );
298    
299            String sRetVal = "Average Function NCSS: "
300                + Util.paddWithSpace(_pNumberFormat.format(fAverageNcss), 10) + NL
301                + "Average Function CCN:  "
302                + Util.paddWithSpace(_pNumberFormat.format(fAverageCCN),  10) + NL
303                + "Average Function JVDC: "
304                + Util.paddWithSpace(_pNumberFormat.format(fAverageJVDC), 10) + NL
305                + "Program NCSS:          "
306                + Util.paddWithSpace(_pNumberFormat.format(_javancss.getNcss()), 10) + NL;
307    
308            return sRetVal;
309        }
310    
311        public String printFunctionNcss()
312        {
313            StringBuffer sRetVal = new StringBuffer(80000);
314    
315            List vFunctionMetrics = _javancss.getFunctionMetrics();
316    
317            sRetVal.append( _formatListHeader( vFunctionMetrics.size()
318                                               , new String[] { "NCSS"
319                                                                , "CCN"
320                                                                , "JVDC"
321                                                                , "Function" } ) );
322    
323            long lFunctionSum = 0;
324            long lCCNSum      = 0;
325            long lJVDCSum     = 0;
326            for( Iterator eFunctions = vFunctionMetrics.iterator(); eFunctions.hasNext(); )
327            {
328                FunctionMetric functionMetric = (FunctionMetric)eFunctions.next();
329                String sFunction = functionMetric.name;
330                int functionNcss = functionMetric.ncss;
331                int functionCCN  = functionMetric.ccn;
332                int functionJVDC = functionMetric.javadocs;
333    
334                lFunctionSum += (long)functionNcss;
335                lCCNSum      += (long)functionCCN;
336                lJVDCSum     += (long)functionJVDC;
337                sRetVal.append( _formatListLine( sFunction
338                                                 , new int[] { functionNcss
339                                                               , functionCCN
340                                                               , functionJVDC } ) );
341            }
342    
343            sRetVal.append( _formatFunctionResume( vFunctionMetrics.size()
344                                                   , lFunctionSum
345                                                   , lCCNSum
346                                                   , lJVDCSum              ) );
347    
348            return sRetVal.toString();
349        }
350    
351        public String printJavaNcss()
352        {
353            return "Java NCSS: " + _javancss.getNcss() + NL;
354        }
355    }