private void constructPackagesSection( ResourceBundle bundle, Sink sink, Map suitePackages )
    {
        NumberFormat numberFormat = report.getNumberFormat();

        sink.section1();
        sink.sectionTitle1();
        sink.text( bundle.getString( "report.surefire.label.packagelist" ) );
        sink.sectionTitle1_();

        sinkAnchor( sink, "Package_List" );

        constructHotLinks( sink, bundle );

        sinkLineBreak( sink );

        sink.table();

        sink.tableRow();

        sinkHeader( sink, bundle.getString( "report.surefire.label.package" ) );

        sinkHeader( sink, bundle.getString( "report.surefire.label.tests" ) );

        sinkHeader( sink, bundle.getString( "report.surefire.label.errors" ) );

        sinkHeader( sink, bundle.getString( "report.surefire.label.failures" ) );

        sinkHeader( sink, bundle.getString( "report.surefire.label.skipped" ) );

        sinkHeader( sink, bundle.getString( "report.surefire.label.successrate" ) );

        sinkHeader( sink, bundle.getString( "report.surefire.label.time" ) );

        sink.tableRow_();

        Iterator packIter = suitePackages.keySet().iterator();

        while ( packIter.hasNext() )
        {
            sink.tableRow();

            String packageName = (String) packIter.next();

            List testSuiteList = (List) suitePackages.get( packageName );

            Map packageSummary = report.getSummary( testSuiteList );

            sinkCellLink( sink, packageName, "#" + packageName );

            sinkCell( sink, (String) packageSummary.get( "totalTests" ) );

            sinkCell( sink, (String) packageSummary.get( "totalErrors" ) );

            sinkCell( sink, (String) packageSummary.get( "totalFailures" ) );

            sinkCell( sink, (String) packageSummary.get( "totalSkipped" ) );

            sinkCell( sink, packageSummary.get( "totalPercentage" ) + "%" );

            sinkCell( sink, (String) packageSummary.get( "totalElapsedTime" ) );

            sink.tableRow_();
        }

        sink.table_();

        sink.lineBreak();

        sink.paragraph();
        sink.text( bundle.getString( "report.surefire.text.note2" ) );
        sink.paragraph_();

        packIter = suitePackages.keySet().iterator();

        while ( packIter.hasNext() )
        {
            String packageName = (String) packIter.next();

            List testSuiteList = (List) suitePackages.get( packageName );

            Iterator suiteIterator = testSuiteList.iterator();

            sink.section2();
            sink.sectionTitle2();
            sink.text( packageName );
            sink.sectionTitle2_();

            sinkAnchor( sink, packageName );

            sink.table();

            sink.tableRow();

            sinkHeader( sink, "" );

            sinkHeader( sink, bundle.getString( "report.surefire.label.class" ) );

            sinkHeader( sink, bundle.getString( "report.surefire.label.tests" ) );

            sinkHeader( sink, bundle.getString( "report.surefire.label.errors" ) );

            sinkHeader( sink, bundle.getString( "report.surefire.label.failures" ) );

            sinkHeader( sink, bundle.getString( "report.surefire.label.skipped" ) );

            sinkHeader( sink, bundle.getString( "report.surefire.label.successrate" ) );

            sinkHeader( sink, bundle.getString( "report.surefire.label.time" ) );

            sink.tableRow_();

            while ( suiteIterator.hasNext() )
            {
                ReportTestSuite suite = (ReportTestSuite) suiteIterator.next();

                if ( showSuccess || suite.getNumberOfErrors() != 0 || suite.getNumberOfFailures() != 0 )
                {

                    sink.tableRow();

                    sink.tableCell();

                    sink.link( "#" + suite.getPackageName() + suite.getName() );

                    if ( suite.getNumberOfErrors() > 0 )
                    {
                        sinkIcon( "error", sink );
                    }
                    else if ( suite.getNumberOfFailures() > 0 )
                    {
                        sinkIcon( "junit.framework", sink );
                    }
                    else if ( suite.getNumberOfSkipped() > 0 )
                    {
                        sinkIcon( "skipped", sink );
                    }
                    else
                    {
                        sinkIcon( "success", sink );
                    }

                    sink.link_();

                    sink.tableCell_();

                    sinkCellLink( sink, suite.getName(), "#" + suite.getPackageName() + suite.getName() );

                    sinkCell( sink, Integer.toString( suite.getNumberOfTests() ) );

                    sinkCell( sink, Integer.toString( suite.getNumberOfErrors() ) );

                    sinkCell( sink, Integer.toString( suite.getNumberOfFailures() ) );

                    sinkCell( sink, Integer.toString( suite.getNumberOfSkipped() ) );

                    String percentage = report.computePercentage( suite.getNumberOfTests(), suite.getNumberOfErrors(),
                                                                  suite.getNumberOfFailures(), suite
                        .getNumberOfSkipped() );
                    sinkCell( sink, percentage + "%" );

                    sinkCell( sink, numberFormat.format( suite.getTimeElapsed() ) );

                    sink.tableRow_();
                }
            }

            sink.table_();

            sink.section2_();
        }

        sinkLineBreak( sink );

        sink.section1_();
    }