Coverage Report - org.apache.maven.plugins.linkcheck.LinkcheckReportGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
LinkcheckReportGenerator
0%
0/320
0%
0/54
2,438
 
 1  
 /*
 2  
  *  Licensed under the Apache License, Version 2.0 (the "License");
 3  
  *  you may not use this file except in compliance with the License.
 4  
  *  You may obtain a copy of the License at
 5  
  * 
 6  
  *       http://www.apache.org/licenses/LICENSE-2.0
 7  
  * 
 8  
  *  Unless required by applicable law or agreed to in writing, software
 9  
  *  distributed under the License is distributed on an "AS IS" BASIS,
 10  
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 11  
  *  See the License for the specific language governing permissions and
 12  
  *  limitations under the License.
 13  
  */
 14  
 
 15  
 package org.apache.maven.plugins.linkcheck;
 16  
 
 17  
 import java.util.Iterator;
 18  
 import java.util.List;
 19  
 import java.util.Locale;
 20  
 
 21  
 import org.apache.commons.io.FilenameUtils;
 22  
 
 23  
 import org.apache.maven.doxia.linkcheck.model.LinkcheckFile;
 24  
 import org.apache.maven.doxia.linkcheck.model.LinkcheckFileResult;
 25  
 import org.apache.maven.doxia.linkcheck.model.LinkcheckModel;
 26  
 import org.apache.maven.doxia.sink.Sink;
 27  
 
 28  
 import org.codehaus.plexus.i18n.I18N;
 29  
 import org.codehaus.plexus.util.StringUtils;
 30  
 
 31  
 /**
 32  
  *
 33  
  * @author ltheussl
 34  
  * @since 1.1
 35  
  */
 36  
 public class LinkcheckReportGenerator
 37  
 {
 38  
     private final I18N i18n;
 39  
 
 40  
     private String httpMethod;
 41  
     private boolean offline;
 42  
     private String[] excludedLinks;
 43  
     private Integer[] excludedHttpStatusErrors;
 44  
     private Integer[] excludedHttpStatusWarnings;
 45  
     private String[] excludedPages;
 46  
     private boolean httpFollowRedirect;
 47  
 
 48  
     /**
 49  
      *
 50  
      * @param i18n not null.
 51  
      */
 52  
     public LinkcheckReportGenerator( I18N i18n )
 53  0
     {
 54  0
         this.i18n = i18n;
 55  0
     }
 56  
 
 57  
     /**
 58  
      *
 59  
      * @param excludedHttpStatusErrors may be null.
 60  
      */
 61  
     public void setExcludedHttpStatusErrors( Integer[] excludedHttpStatusErrors )
 62  
     {
 63  0
         this.excludedHttpStatusErrors = excludedHttpStatusErrors;
 64  0
     }
 65  
 
 66  
     /**
 67  
      *
 68  
      * @param excludedHttpStatusWarnings may be null.
 69  
      */
 70  
     public void setExcludedHttpStatusWarnings( Integer[] excludedHttpStatusWarnings )
 71  
     {
 72  0
         this.excludedHttpStatusWarnings = excludedHttpStatusWarnings;
 73  0
     }
 74  
 
 75  
     /**
 76  
      *
 77  
      * @param excludedLinks may be null.
 78  
      */
 79  
     public void setExcludedLinks( String[] excludedLinks )
 80  
     {
 81  0
         this.excludedLinks = excludedLinks;
 82  0
     }
 83  
 
 84  
     /**
 85  
      *
 86  
      * @param excludedPages may be null.
 87  
      */
 88  
     public void setExcludedPages( String[] excludedPages )
 89  
     {
 90  0
         this.excludedPages = excludedPages;
 91  0
     }
 92  
 
 93  
     /**
 94  
      *
 95  
      * @param httpFollowRedirect default is false.
 96  
      */
 97  
     public void setHttpFollowRedirect( boolean httpFollowRedirect )
 98  
     {
 99  0
         this.httpFollowRedirect = httpFollowRedirect;
 100  0
     }
 101  
 
 102  
     /**
 103  
      *
 104  
      * @param httpMethod may be null.
 105  
      */
 106  
     public void setHttpMethod( String httpMethod )
 107  
     {
 108  0
         this.httpMethod = httpMethod;
 109  0
     }
 110  
 
 111  
     /**
 112  
      *
 113  
      * @param offline default is false.
 114  
      */
 115  
     public void setOffline( boolean offline )
 116  
     {
 117  0
         this.offline = offline;
 118  0
     }
 119  
 
 120  
     /**
 121  
      * Genarate a report for the given LinkcheckModel and emit it into a Sink.
 122  
      * <strong>Note</strong> that the Sink is flushed and closed.
 123  
      *
 124  
      * @param locale not null.
 125  
      * @param linkcheckModel may be null.
 126  
      * @param sink not null.
 127  
      */
 128  
     public void generateReport( Locale locale, LinkcheckModel linkcheckModel, Sink sink )
 129  
     {
 130  0
         String name = i18n.getString( "linkcheck-report", locale, "report.linkcheck.name" );
 131  
 
 132  0
         sink.head();
 133  0
         sink.title();
 134  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.title" ) );
 135  0
         sink.title_();
 136  0
         sink.head_();
 137  
 
 138  0
         sink.body();
 139  
 
 140  0
         if ( linkcheckModel == null )
 141  
         {
 142  0
             sink.section1();
 143  0
             sink.sectionTitle1();
 144  0
             sink.text( name );
 145  0
             sink.sectionTitle1_();
 146  
 
 147  0
             sink.paragraph();
 148  0
             sink.rawText( i18n.getString( "linkcheck-report", locale, "report.linkcheck.empty" ) );
 149  0
             sink.paragraph_();
 150  
 
 151  0
             sink.section1_();
 152  
 
 153  0
             sink.body_();
 154  0
             sink.flush();
 155  0
             sink.close();
 156  
 
 157  0
             return;
 158  
         }
 159  
 
 160  
         // Overview
 161  0
         sink.section1();
 162  0
         sink.sectionTitle1();
 163  0
         sink.text( name );
 164  0
         sink.sectionTitle1_();
 165  
 
 166  0
         sink.paragraph();
 167  0
         sink.rawText( i18n.getString( "linkcheck-report", locale, "report.linkcheck.overview" ) );
 168  0
         sink.paragraph_();
 169  
 
 170  0
         sink.section1_();
 171  
 
 172  
         // Statistics
 173  0
         generateSummarySection( locale, linkcheckModel, sink );
 174  
 
 175  0
         if ( linkcheckModel.getFiles().size() > 0 )
 176  
         {
 177  
             // Details
 178  0
             generateDetailsSection( locale, linkcheckModel, sink );
 179  
         }
 180  
 
 181  0
         sink.body_();
 182  0
         sink.flush();
 183  0
         sink.close();
 184  0
     }
 185  
 
 186  
     private void generateSummarySection( Locale locale, LinkcheckModel linkcheckModel, Sink sink )
 187  
     {
 188  
         // Calculus
 189  0
         List linkcheckFiles = linkcheckModel.getFiles();
 190  
 
 191  0
         int totalFiles = linkcheckFiles.size();
 192  
 
 193  0
         int totalLinks = 0;
 194  0
         int totalValidLinks = 0;
 195  0
         int totalErrorLinks = 0;
 196  0
         int totalWarningLinks = 0;
 197  0
         for ( Iterator it = linkcheckFiles.iterator(); it.hasNext(); )
 198  
         {
 199  0
             LinkcheckFile linkcheckFile = (LinkcheckFile) it.next();
 200  
 
 201  0
             totalLinks += linkcheckFile.getNumberOfLinks();
 202  0
             totalValidLinks += linkcheckFile.getNumberOfLinks( LinkcheckFileResult.VALID_LEVEL );
 203  0
             totalErrorLinks += linkcheckFile.getNumberOfLinks( LinkcheckFileResult.ERROR_LEVEL );
 204  0
             totalWarningLinks += linkcheckFile.getNumberOfLinks( LinkcheckFileResult.WARNING_LEVEL );
 205  0
         }
 206  
 
 207  0
         sink.section1();
 208  0
         sink.sectionTitle1();
 209  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary" ) );
 210  0
         sink.sectionTitle1_();
 211  
 
 212  
         // Summary of the analysis parameters
 213  0
         sink.paragraph();
 214  0
         sink.rawText( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.overview1" ) );
 215  0
         sink.paragraph_();
 216  
 
 217  0
         sink.table();
 218  
 
 219  0
         sink.tableRow();
 220  0
         sink.tableHeaderCell();
 221  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.parameter" ) );
 222  0
         sink.tableHeaderCell_();
 223  0
         sink.tableHeaderCell();
 224  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.value" ) );
 225  0
         sink.tableHeaderCell_();
 226  0
         sink.tableRow_();
 227  
 
 228  0
         sink.tableRow();
 229  0
         sink.tableCell();
 230  0
         sink.rawText(
 231  
                            i18n.getString( "linkcheck-report", locale,
 232  
                                            "report.linkcheck.summary.table.httpFollowRedirect" ) );
 233  0
         sink.tableCell_();
 234  0
         sink.tableCell();
 235  0
         sink.text( String.valueOf( httpFollowRedirect ) );
 236  0
         sink.tableCell_();
 237  0
         sink.tableRow_();
 238  
 
 239  0
         sink.tableRow();
 240  0
         sink.tableCell();
 241  0
         sink
 242  
                  .rawText(
 243  
                            i18n
 244  
                                .getString( "linkcheck-report", locale, "report.linkcheck.summary.table.httpMethod" ) );
 245  0
         sink.tableCell_();
 246  0
         sink.tableCell();
 247  0
         if ( StringUtils.isEmpty( httpMethod ) )
 248  
         {
 249  0
             sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.none" ) );
 250  
         }
 251  
         else
 252  
         {
 253  0
             sink.text( httpMethod );
 254  
         }
 255  0
         sink.tableCell_();
 256  0
         sink.tableRow_();
 257  
 
 258  0
         sink.tableRow();
 259  0
         sink.tableCell();
 260  0
         sink.rawText(
 261  
                            i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.offline" ) );
 262  0
         sink.tableCell_();
 263  0
         sink.tableCell();
 264  0
         sink.text( String.valueOf( offline ) );
 265  0
         sink.tableCell_();
 266  0
         sink.tableRow_();
 267  
 
 268  0
         sink.tableRow();
 269  0
         sink.tableCell();
 270  0
         sink.rawText(
 271  
                            i18n.getString( "linkcheck-report", locale,
 272  
                                            "report.linkcheck.summary.table.excludedPages" ) );
 273  0
         sink.tableCell_();
 274  0
         sink.tableCell();
 275  0
         if ( excludedPages == null || excludedPages.length == 0 )
 276  
         {
 277  0
             sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.none" ) );
 278  
         }
 279  
         else
 280  
         {
 281  0
             sink.text( StringUtils.join( excludedPages, "," ) );
 282  
         }
 283  0
         sink.tableCell_();
 284  0
         sink.tableRow_();
 285  
 
 286  0
         sink.tableRow();
 287  0
         sink.tableCell();
 288  0
         sink.rawText(
 289  
                            i18n.getString( "linkcheck-report", locale,
 290  
                                            "report.linkcheck.summary.table.excludedLinks" ) );
 291  0
         sink.tableCell_();
 292  0
         sink.tableCell();
 293  0
         if ( excludedLinks == null || excludedLinks.length == 0 )
 294  
         {
 295  0
             sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.none" ) );
 296  
         }
 297  
         else
 298  
         {
 299  0
             sink.text( StringUtils.join( excludedLinks, "," ) );
 300  
         }
 301  0
         sink.tableCell_();
 302  0
         sink.tableRow_();
 303  
 
 304  0
         sink.tableRow();
 305  0
         sink.tableCell();
 306  0
         sink.rawText(
 307  
                            i18n.getString( "linkcheck-report", locale,
 308  
                                            "report.linkcheck.summary.table.excludedHttpStatusErrors" ) );
 309  0
         sink.tableCell_();
 310  0
         sink.tableCell();
 311  0
         if ( excludedHttpStatusErrors == null || excludedHttpStatusErrors.length == 0 )
 312  
         {
 313  0
             sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.none" ) );
 314  
         }
 315  
         else
 316  
         {
 317  0
             sink.text( toString( excludedHttpStatusErrors ) );
 318  
         }
 319  0
         sink.tableCell_();
 320  0
         sink.tableRow_();
 321  
 
 322  0
         sink.tableRow();
 323  0
         sink.tableCell();
 324  0
         sink.rawText(
 325  
                            i18n.getString( "linkcheck-report", locale,
 326  
                                            "report.linkcheck.summary.table.excludedHttpStatusWarnings" ) );
 327  0
         sink.tableCell_();
 328  0
         sink.tableCell();
 329  0
         if ( excludedHttpStatusWarnings == null || excludedHttpStatusWarnings.length == 0 )
 330  
         {
 331  0
             sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.table.none" ) );
 332  
         }
 333  
         else
 334  
         {
 335  0
             sink.text( toString( excludedHttpStatusWarnings ) );
 336  
         }
 337  0
         sink.tableCell_();
 338  0
         sink.tableRow_();
 339  
 
 340  0
         sink.table_();
 341  
 
 342  
         // Summary of the checked files
 343  0
         sink.paragraph();
 344  0
         sink.rawText( i18n.getString( "linkcheck-report", locale, "report.linkcheck.summary.overview2" ) );
 345  0
         sink.paragraph_();
 346  
 
 347  0
         sink.table();
 348  
 
 349  
         // Header
 350  0
         generateTableHeader( locale, false, sink );
 351  
 
 352  
         // Content
 353  0
         sink.tableRow();
 354  
 
 355  0
         sink.tableCell();
 356  0
         sink.bold();
 357  0
         sink.text( totalFiles + "" );
 358  0
         sink.bold_();
 359  0
         sink.tableCell_();
 360  0
         sink.tableCell();
 361  0
         sink.bold();
 362  0
         sink.text( totalLinks + "" );
 363  0
         sink.bold_();
 364  0
         sink.tableCell_();
 365  0
         sink.tableCell();
 366  0
         sink.bold();
 367  0
         sink.text( String.valueOf( totalValidLinks ) );
 368  0
         sink.bold_();
 369  0
         sink.tableCell_();
 370  0
         sink.tableCell();
 371  0
         sink.bold();
 372  0
         sink.text( String.valueOf( totalWarningLinks ) );
 373  0
         sink.bold_();
 374  0
         sink.tableCell_();
 375  0
         sink.tableCell();
 376  0
         sink.bold();
 377  0
         sink.text( String.valueOf( totalErrorLinks ) );
 378  0
         sink.bold_();
 379  0
         sink.tableCell_();
 380  
 
 381  0
         sink.tableRow_();
 382  
 
 383  0
         sink.table_();
 384  
 
 385  0
         sink.section1_();
 386  0
     }
 387  
 
 388  
     private void generateDetailsSection( Locale locale, LinkcheckModel linkcheckModel, Sink sink )
 389  
     {
 390  0
         sink.section1();
 391  0
         sink.sectionTitle1();
 392  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.detail" ) );
 393  0
         sink.sectionTitle1_();
 394  
 
 395  0
         sink.paragraph();
 396  0
         sink.rawText( i18n.getString( "linkcheck-report", locale, "report.linkcheck.detail.overview" ) );
 397  0
         sink.paragraph_();
 398  
 
 399  0
         sink.table();
 400  
 
 401  
         // Header
 402  0
         generateTableHeader( locale, true, sink );
 403  
 
 404  
         // Content
 405  0
         List linkcheckFiles = linkcheckModel.getFiles();
 406  0
         for ( Iterator it = linkcheckFiles.iterator(); it.hasNext(); )
 407  
         {
 408  0
             LinkcheckFile linkcheckFile = (LinkcheckFile) it.next();
 409  
 
 410  0
             sink.tableRow();
 411  
 
 412  0
             sink.tableCell();
 413  0
             if ( linkcheckFile.getUnsuccessful() == 0 )
 414  
             {
 415  0
                 iconValid( locale, sink );
 416  
             }
 417  
             else
 418  
             {
 419  0
                 iconError( locale, sink );
 420  
             }
 421  0
             sink.tableCell_();
 422  
 
 423  
             // tableCell( createLinkPatternedText( linkcheckFile.getRelativePath(), "./"
 424  
             // + linkcheckFile.getRelativePath() ) );
 425  0
             sink.tableCell();
 426  0
             sink.link( linkcheckFile.getRelativePath() );
 427  0
             sink.text( linkcheckFile.getRelativePath() );
 428  0
             sink.link_();
 429  0
             sink.tableCell_();
 430  0
             sink.tableCell();
 431  0
             sink.text( String.valueOf( linkcheckFile.getNumberOfLinks() ) );
 432  0
             sink.tableCell_();
 433  0
             sink.tableCell();
 434  0
             sink.text( String.valueOf( linkcheckFile.getNumberOfLinks( LinkcheckFileResult.VALID_LEVEL ) ) );
 435  0
             sink.tableCell_();
 436  0
             sink.tableCell();
 437  0
             sink.text( String.valueOf( linkcheckFile.getNumberOfLinks( LinkcheckFileResult.WARNING_LEVEL ) ) );
 438  0
             sink.tableCell_();
 439  0
             sink.tableCell();
 440  0
             sink.text( String.valueOf( linkcheckFile.getNumberOfLinks( LinkcheckFileResult.ERROR_LEVEL ) ) );
 441  0
             sink.tableCell_();
 442  
 
 443  0
             sink.tableRow_();
 444  
 
 445  
             // Detail error
 446  0
             if ( linkcheckFile.getUnsuccessful() != 0 )
 447  
             {
 448  0
                 sink.tableRow();
 449  
 
 450  0
                 sink.tableCell();
 451  0
                 sink.text( "" );
 452  0
                 sink.tableCell_();
 453  
 
 454  
                 // TODO it is due to DOXIA-78
 455  0
                 sink.rawText( "<td colspan=\"5\">" );
 456  
 
 457  0
                 sink.table();
 458  
 
 459  0
                 for ( Iterator it2 = linkcheckFile.getResults().iterator(); it2.hasNext(); )
 460  
                 {
 461  0
                     LinkcheckFileResult linkcheckFileResult = (LinkcheckFileResult) it2.next();
 462  
 
 463  0
                     if ( linkcheckFileResult.getStatusLevel() == LinkcheckFileResult.VALID_LEVEL )
 464  
                     {
 465  0
                         continue;
 466  
                     }
 467  
 
 468  0
                     sink.tableRow();
 469  
 
 470  0
                     sink.tableCell();
 471  0
                     if ( linkcheckFileResult.getStatusLevel() == LinkcheckFileResult.WARNING_LEVEL )
 472  
                     {
 473  0
                         iconWarning( locale, sink );
 474  
                     }
 475  0
                     else if ( linkcheckFileResult.getStatusLevel() == LinkcheckFileResult.ERROR_LEVEL )
 476  
                     {
 477  0
                         iconError( locale, sink );
 478  
                     }
 479  0
                     sink.tableCell_();
 480  
 
 481  0
                     sink.tableCell();
 482  0
                     sink.italic();
 483  0
                     if ( linkcheckFileResult.getTarget().startsWith( "#" ) )
 484  
                     {
 485  0
                         sink.link( linkcheckFile.getRelativePath() + linkcheckFileResult.getTarget() );
 486  
                     }
 487  0
                     else if ( linkcheckFileResult.getTarget().startsWith( "." ) )
 488  
                     {
 489  
                         // We need to calculate a correct absolute path here, because target is a relative path
 490  0
                         String absolutePath = FilenameUtils.getFullPath( linkcheckFile.getRelativePath() )
 491  
                             + linkcheckFileResult.getTarget();
 492  0
                         String normalizedPath = FilenameUtils.normalize( absolutePath );
 493  0
                         if ( normalizedPath == null )
 494  
                         {
 495  0
                             normalizedPath = absolutePath;
 496  
                         }
 497  0
                         sink.link( normalizedPath );
 498  0
                     }
 499  
                     else
 500  
                     {
 501  0
                         sink.link( linkcheckFileResult.getTarget() );
 502  
                     }
 503  
                     // Show the link as it was written to make it easy for
 504  
                     // the author to find it in the source document
 505  0
                     sink.text( linkcheckFileResult.getTarget() );
 506  0
                     sink.link_();
 507  0
                     sink.text( ": " );
 508  0
                     sink.text( linkcheckFileResult.getErrorMessage() );
 509  0
                     sink.italic_();
 510  0
                     sink.tableCell_();
 511  
 
 512  0
                     sink.tableRow_();
 513  0
                 }
 514  
 
 515  0
                 sink.table_();
 516  
 
 517  0
                 sink.tableCell_();
 518  
 
 519  0
                 sink.tableRow_();
 520  
             }
 521  0
         }
 522  
 
 523  0
         sink.table_();
 524  
 
 525  0
         sink.section1_();
 526  0
     }
 527  
 
 528  
     private void generateTableHeader( Locale locale, boolean detail, Sink sink )
 529  
     {
 530  0
         sink.tableRow();
 531  0
         if ( detail )
 532  
         {
 533  0
             sink.rawText( "<th rowspan=\"2\">" );
 534  0
             sink.text( "" );
 535  0
             sink.tableHeaderCell_();
 536  
         }
 537  0
         sink.rawText( "<th rowspan=\"2\">" );
 538  0
         sink.text(
 539  
                         detail ? i18n.getString( "linkcheck-report", locale,
 540  
                                                  "report.linkcheck.detail.table.documents" )
 541  
                                         : i18n.getString( "linkcheck-report", locale,
 542  
                                                           "report.linkcheck.summary.table.documents" ) );
 543  0
         sink.tableHeaderCell_();
 544  
         // TODO it is due to DOXIA-78
 545  0
         sink.rawText( "<th colspan=\"4\" align=\"center\">" );
 546  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.table.links" ) );
 547  0
         sink.tableHeaderCell_();
 548  0
         sink.tableRow_();
 549  
 
 550  0
         sink.tableRow();
 551  0
         sink.tableHeaderCell();
 552  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.table.totalLinks" ) );
 553  0
         sink.tableHeaderCell_();
 554  0
         sink.tableHeaderCell();
 555  0
         iconValid( locale, sink );
 556  0
         sink.tableHeaderCell_();
 557  0
         sink.tableHeaderCell();
 558  0
         iconWarning( locale, sink );
 559  0
         sink.tableHeaderCell_();
 560  0
         sink.tableHeaderCell();
 561  0
         iconError( locale, sink );
 562  0
         sink.tableHeaderCell_();
 563  0
         sink.tableRow_();
 564  0
     }
 565  
 
 566  
     private void iconError( Locale locale, Sink sink )
 567  
     {
 568  0
         sink.figure();
 569  0
         sink.figureCaption();
 570  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.icon.error" ) );
 571  0
         sink.figureCaption_();
 572  0
         sink.figureGraphics( LinkcheckReport.ICON_ERROR );
 573  0
         sink.figure_();
 574  0
     }
 575  
 
 576  
     private void iconValid( Locale locale, Sink sink )
 577  
     {
 578  0
         sink.figure();
 579  0
         sink.figureCaption();
 580  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.icon.valid" ) );
 581  0
         sink.figureCaption_();
 582  0
         sink.figureGraphics( LinkcheckReport.ICON_SUCCESS );
 583  0
         sink.figure_();
 584  0
     }
 585  
 
 586  
     private void iconWarning( Locale locale, Sink sink )
 587  
     {
 588  0
         sink.figure();
 589  0
         sink.figureCaption();
 590  0
         sink.text( i18n.getString( "linkcheck-report", locale, "report.linkcheck.icon.warning" ) );
 591  0
         sink.figureCaption_();
 592  0
         sink.figureGraphics( LinkcheckReport.ICON_WARNING );
 593  0
         sink.figure_();
 594  0
     }
 595  
 
 596  
     // ----------------------------------------------------------------------
 597  
     // static methods
 598  
     // ----------------------------------------------------------------------
 599  
 
 600  
     /**
 601  
      * Similar to {@link Arrays#toString(int[])} in 1.5.
 602  
      *
 603  
      * @param a not null
 604  
      * @return the array comma separated.
 605  
      */
 606  
     private static String toString( Object[] a )
 607  
     {
 608  0
         if ( a == null || a.length == 0 )
 609  
         {
 610  0
             return "";
 611  
         }
 612  
 
 613  0
         StringBuffer buf = new StringBuffer();
 614  0
         buf.append( a[0] );
 615  
 
 616  0
         for ( int i = 1; i < a.length; i++ )
 617  
         {
 618  0
             buf.append( ", " );
 619  0
             buf.append( a[i] );
 620  
         }
 621  
 
 622  0
         return buf.toString();
 623  
     }
 624  
 }