Coverage Report - org.apache.maven.plugin.changes.ChangesReportGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
ChangesReportGenerator
0%
0/170
0%
0/82
0
 
 1  
 package org.apache.maven.plugin.changes;
 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.util.HashMap;
 23  
 import java.util.Iterator;
 24  
 import java.util.LinkedHashMap;
 25  
 import java.util.List;
 26  
 import java.util.Map;
 27  
 import java.util.ResourceBundle;
 28  
 
 29  
 import org.apache.commons.lang.StringUtils;
 30  
 import org.apache.maven.doxia.sink.Sink;
 31  
 import org.apache.maven.doxia.util.HtmlTools;
 32  
 import org.apache.maven.plugin.issues.AbstractIssuesReportGenerator;
 33  
 import org.apache.maven.plugins.changes.model.Action;
 34  
 import org.apache.maven.plugins.changes.model.DueTo;
 35  
 import org.apache.maven.plugins.changes.model.FixedIssue;
 36  
 import org.apache.maven.plugins.changes.model.Release;
 37  
 
 38  
 /**
 39  
  * Generates a changes report.
 40  
  *
 41  
  * @version $Id: org.apache.maven.plugin.changes.ChangesReportGenerator.html 816601 2012-05-08 12:50:18Z hboutemy $
 42  
  */
 43  
 public class ChangesReportGenerator extends AbstractIssuesReportGenerator
 44  
 {
 45  
 
 46  
     /**
 47  
      * The token in {@link #issueLinksPerSystem} denoting the base URL for the issue management.
 48  
      */
 49  
     private static final String URL_TOKEN = "%URL%";
 50  
 
 51  
     /**
 52  
      * The token in {@link #issueLinksPerSystem} denoting the issue ID.
 53  
      */
 54  
     private static final String ISSUE_TOKEN = "%ISSUE%";
 55  
 
 56  
     static final String DEFAULT_ISSUE_SYSTEM_KEY = "default";
 57  
 
 58  
     private static final String NO_TEAMLIST = "none";
 59  
 
 60  
     /**
 61  
      * The issue management system to use, for actions that do not specify a
 62  
      * system.
 63  
      *
 64  
      * @since 2.4
 65  
      */
 66  
     private String system;
 67  
 
 68  
     private String teamlist;
 69  
 
 70  
     private String url;
 71  
 
 72  
     private Map issueLinksPerSystem;
 73  
 
 74  
     private boolean addActionDate;
 75  
 
 76  
     /**
 77  
      * @since 2.4
 78  
      */
 79  
     private boolean escapeHTML;
 80  
 
 81  
     /**
 82  
      * @since 2.4
 83  
      */
 84  
     private List releaseList;
 85  
 
 86  
     public ChangesReportGenerator()
 87  0
     {
 88  0
         issueLinksPerSystem = new HashMap();
 89  0
     }
 90  
 
 91  
     public ChangesReportGenerator( List releaseList )
 92  
     {
 93  0
         this();
 94  0
         this.releaseList = releaseList;
 95  0
     }
 96  
 
 97  
     /**
 98  
      * @since 2.4
 99  
      */
 100  
     public boolean isEscapeHTML()
 101  
     {
 102  0
         return escapeHTML;
 103  
     }
 104  
 
 105  
     /**
 106  
      * @since 2.4
 107  
      */
 108  
     public void setEscapeHTML( boolean escapeHTML )
 109  
     {
 110  0
         this.escapeHTML = escapeHTML;
 111  0
     }
 112  
 
 113  
     /**
 114  
      * @since 2.4
 115  
      */
 116  
     public String getSystem()
 117  
     {
 118  0
         return system;
 119  
     }
 120  
 
 121  
     /**
 122  
      * @since 2.4
 123  
      */
 124  
     public void setSystem( String system )
 125  
     {
 126  0
         this.system = system;
 127  0
     }
 128  
 
 129  
     public void setTeamlist( final String teamlist )
 130  
     {
 131  0
         this.teamlist = teamlist;
 132  0
     }
 133  
 
 134  
     public String getTeamlist()
 135  
     {
 136  0
         return teamlist;
 137  
     }
 138  
 
 139  
     public void setUrl( String url )
 140  
     {
 141  0
         this.url = url;
 142  0
     }
 143  
 
 144  
     public String getUrl()
 145  
     {
 146  0
         return url;
 147  
     }
 148  
 
 149  
     public Map getIssueLinksPerSystem()
 150  
     {
 151  0
         return issueLinksPerSystem;
 152  
     }
 153  
 
 154  
     public void setIssueLinksPerSystem( Map issueLinksPerSystem )
 155  
     {
 156  0
         if ( this.issueLinksPerSystem != null && issueLinksPerSystem == null )
 157  
         {
 158  0
             return;
 159  
         }
 160  0
         this.issueLinksPerSystem = issueLinksPerSystem;
 161  0
     }
 162  
 
 163  
     public boolean isAddActionDate()
 164  
     {
 165  0
         return addActionDate;
 166  
     }
 167  
 
 168  
     public void setAddActionDate( boolean addActionDate )
 169  
     {
 170  0
         this.addActionDate = addActionDate;
 171  0
     }
 172  
 
 173  
     /**
 174  
      * Checks whether links to the issues can be generated for the given system.
 175  
      *
 176  
      * @param system The issue management system
 177  
      * @return <code>true</code> if issue links can be generated, <code>false</code> otherwise.
 178  
      */
 179  
     public boolean canGenerateIssueLinks( String system )
 180  
     {
 181  0
         if ( !this.issueLinksPerSystem.containsKey( system ) )
 182  
         {
 183  0
             return false;
 184  
         }
 185  0
         String issueLink = (String) this.issueLinksPerSystem.get( system );
 186  
 
 187  
         // If the issue link entry is blank then no links are possible
 188  0
         if ( StringUtils.isBlank( issueLink ) )
 189  
         {
 190  0
             return false;
 191  
         }
 192  
 
 193  
         // If the %URL% token is used then the issue management system URL must be set.
 194  0
         if ( issueLink.indexOf( URL_TOKEN ) >= 0 && StringUtils.isBlank( getUrl() ) )
 195  
         {
 196  0
             return false;
 197  
         }
 198  0
         return true;
 199  
     }
 200  
 
 201  
     public void doGenerateEmptyReport( ResourceBundle bundle, Sink sink, String message )
 202  
     {
 203  0
         sinkBeginReport( sink, bundle );
 204  
 
 205  0
         sink.text( message );
 206  
 
 207  0
         sinkEndReport( sink );
 208  0
     }
 209  
 
 210  
     public void doGenerateReport( ResourceBundle bundle, Sink sink )
 211  
     {
 212  0
         sinkBeginReport( sink, bundle );
 213  
 
 214  0
         constructReleaseHistory( sink, bundle, releaseList );
 215  
 
 216  0
         constructReleases( sink, bundle, releaseList );
 217  
 
 218  0
         sinkEndReport( sink );
 219  0
     }
 220  
 
 221  
     private void constructActions( Sink sink, List actionList, ResourceBundle bundle )
 222  
     {
 223  0
         if ( actionList.isEmpty() )
 224  
         {
 225  0
             sink.paragraph();
 226  
 
 227  0
             sink.text( bundle.getString( "report.changes.text.no.changes" ) );
 228  
 
 229  0
             sink.paragraph_();
 230  
         }
 231  
         else
 232  
         {
 233  0
             sink.table();
 234  
 
 235  0
             sink.tableRow();
 236  
 
 237  0
             sinkHeader( sink, bundle.getString( "report.issues.label.type" ) );
 238  
 
 239  0
             sinkHeader( sink, bundle.getString( "report.issues.label.summary" ) );
 240  
 
 241  0
             sinkHeader( sink, bundle.getString( "report.issues.label.assignee" ) );
 242  
 
 243  0
             if ( this.isAddActionDate() )
 244  
             {
 245  0
                 sinkHeader( sink, bundle.getString( "report.issues.label.updated" ) );
 246  
             }
 247  0
             sink.tableRow_();
 248  
 
 249  0
             for ( int idx = 0; idx < actionList.size(); idx++ )
 250  
             {
 251  0
                 Action action = (Action) actionList.get( idx );
 252  
 
 253  0
                 sink.tableRow();
 254  
 
 255  0
                 sinkShowTypeIcon( sink, action.getType() );
 256  
 
 257  0
                 sink.tableCell();
 258  
 
 259  0
                 if ( escapeHTML )
 260  
                 {
 261  0
                     sink.text( action.getAction() );
 262  
                 }
 263  
                 else
 264  
                 {
 265  0
                     sink.rawText( action.getAction() );
 266  
                 }
 267  
 
 268  
                 // no null check needed classes from modello return a new ArrayList
 269  0
                 if ( StringUtils.isNotEmpty( action.getIssue() ) || ( !action.getFixedIssues().isEmpty() ) )
 270  
                 {
 271  0
                     sink.text( " " + bundle.getString( "report.changes.text.fixes" ) + " " );
 272  
 
 273  
                     // Try to get the issue management system specified in the changes.xml file
 274  0
                     String system = action.getSystem();
 275  
                     // Try to get the issue management system configured in the POM
 276  0
                     if ( StringUtils.isEmpty( system ) )
 277  
                     {
 278  0
                         system = this.system;
 279  
                     }
 280  
                     // Use the default issue management system
 281  0
                     if ( StringUtils.isEmpty( system ) )
 282  
                     {
 283  0
                         system = DEFAULT_ISSUE_SYSTEM_KEY;
 284  
                     }
 285  0
                     if ( !canGenerateIssueLinks( system ) )
 286  
                     {
 287  0
                         constructIssueText( action.getIssue(), sink, action.getFixedIssues() );
 288  
                     }
 289  
                     else
 290  
                     {
 291  0
                         constructIssueLink( action.getIssue(), system, sink, action.getFixedIssues() );
 292  
                     }
 293  0
                     sink.text( "." );
 294  
                 }
 295  
 
 296  0
                 if ( StringUtils.isNotEmpty( action.getDueTo() ) || ( !action.getDueTos().isEmpty() ) )
 297  
                 {
 298  0
                     constructDueTo( sink, action, bundle, action.getDueTos() );
 299  
                 }
 300  
 
 301  0
                 sink.tableCell_();
 302  
 
 303  0
                 if ( NO_TEAMLIST.equals( teamlist ) )
 304  
                 {
 305  0
                     sinkCell( sink, action.getDev() );
 306  
                 }
 307  
                 else
 308  
                 {
 309  0
                     sinkCellLink( sink, action.getDev(), teamlist + "#" + action.getDev() );
 310  
                 }
 311  
 
 312  0
                 if ( this.isAddActionDate() )
 313  
                 {
 314  0
                     sinkCell( sink, action.getDate() );
 315  
                 }
 316  
 
 317  0
                 sink.tableRow_();
 318  
             }
 319  
 
 320  0
             sink.table_();
 321  
         }
 322  0
     }
 323  
 
 324  
     /**
 325  
      * Construct a text or link that mention the people that helped with an action.
 326  
      *
 327  
      * @param sink The sink
 328  
      * @param action The action that was done
 329  
      * @param bundle A resource bundle for i18n
 330  
      * @param dueTos Other people that helped with an action
 331  
      */
 332  
     private void constructDueTo( Sink sink, Action action, ResourceBundle bundle, List dueTos )
 333  
     {
 334  
 
 335  
         // Create a Map with key : dueTo name, value : dueTo email
 336  0
         Map<String,String> namesEmailMap = new LinkedHashMap<String,String>();
 337  
 
 338  
         // Only add the dueTo specified as attributes, if it has either a dueTo or a dueToEmail
 339  0
         if ( StringUtils.isNotEmpty( action.getDueTo() ) || StringUtils.isNotEmpty( action.getDueToEmail() ) )
 340  
         {
 341  0
             namesEmailMap.put( action.getDueTo(), action.getDueToEmail() );
 342  
         }
 343  
 
 344  0
         for ( Iterator iterator = dueTos.iterator(); iterator.hasNext(); )
 345  
         {
 346  0
             DueTo dueTo = (DueTo) iterator.next();
 347  0
             namesEmailMap.put( dueTo.getName(), dueTo.getEmail() );
 348  0
         }
 349  
 
 350  0
         if ( namesEmailMap.isEmpty() )
 351  
         {
 352  0
             return;
 353  
         }
 354  
 
 355  0
         sink.text( " " + bundle.getString( "report.changes.text.thanx" ) + " " );
 356  0
         int i = 0;
 357  0
         for ( String currentDueTo : namesEmailMap.keySet() )
 358  
         {
 359  0
             String currentDueToEmail = namesEmailMap.get( currentDueTo );
 360  0
             i++;
 361  
 
 362  0
             if ( StringUtils.isNotEmpty( currentDueToEmail ) )
 363  
             {
 364  0
                 sinkLink( sink, currentDueTo, "mailto:" + currentDueToEmail );
 365  
             }
 366  0
             else if ( StringUtils.isNotEmpty( currentDueTo ) )
 367  
             {
 368  0
                 sink.text( currentDueTo );
 369  
             }
 370  
 
 371  0
             if ( i < namesEmailMap.size() )
 372  
             {
 373  0
                 sink.text( ", " );
 374  
             }
 375  0
         }
 376  
 
 377  0
         sink.text( "." );
 378  0
     }
 379  
 
 380  
     /**
 381  
      * Construct links to the issues that were solved by an action.
 382  
      *
 383  
      * @param issue The issue specified by attributes
 384  
      * @param system The issue management system
 385  
      * @param sink The sink
 386  
      * @param fixes The List of issues specified as fixes elements
 387  
      */
 388  
     private void constructIssueLink( String issue, String system, Sink sink, List fixes )
 389  
     {
 390  0
         if ( StringUtils.isNotEmpty( issue ) )
 391  
         {
 392  0
             sink.link( parseIssueLink( issue, system ) );
 393  
 
 394  0
             sink.text( issue );
 395  
 
 396  0
             sink.link_();
 397  
 
 398  0
             if ( !fixes.isEmpty() )
 399  
             {
 400  0
                 sink.text( ", " );
 401  
             }
 402  
         }
 403  
 
 404  0
         for ( Iterator iterator = fixes.iterator(); iterator.hasNext(); )
 405  
         {
 406  0
             FixedIssue fixedIssue = (FixedIssue) iterator.next();
 407  0
             String currentIssueId = fixedIssue.getIssue();
 408  0
             if ( StringUtils.isNotEmpty( currentIssueId ) )
 409  
             {
 410  0
                 sink.link( parseIssueLink( currentIssueId, system ) );
 411  
 
 412  0
                 sink.text( currentIssueId );
 413  
 
 414  0
                 sink.link_();
 415  
             }
 416  
 
 417  0
             if ( iterator.hasNext() )
 418  
             {
 419  0
                 sink.text( ", " );
 420  
             }
 421  0
         }
 422  0
     }
 423  
 
 424  
     /**
 425  
      * Construct a text that references (but does not link to) the issues that
 426  
      * were solved by an action.
 427  
      *
 428  
      * @param issue The issue specified by attributes
 429  
      * @param sink The sink
 430  
      * @param fixes The List of issues specified as fixes elements
 431  
      */
 432  
     private void constructIssueText( String issue, Sink sink, List fixes )
 433  
     {
 434  0
         if ( StringUtils.isNotEmpty( issue ) )
 435  
         {
 436  0
             sink.text( issue );
 437  
 
 438  0
             if ( !fixes.isEmpty() )
 439  
             {
 440  0
                 sink.text( ", " );
 441  
             }
 442  
         }
 443  
 
 444  0
         for ( Iterator iterator = fixes.iterator(); iterator.hasNext(); )
 445  
         {
 446  0
             FixedIssue fixedIssue = (FixedIssue) iterator.next();
 447  
 
 448  0
             String currentIssueId = fixedIssue.getIssue();
 449  0
             if ( StringUtils.isNotEmpty( currentIssueId ) )
 450  
             {
 451  0
                 sink.text( currentIssueId );
 452  
             }
 453  
 
 454  0
             if ( iterator.hasNext() )
 455  
             {
 456  0
                 sink.text( ", " );
 457  
             }
 458  0
         }
 459  0
     }
 460  
 
 461  
     private void constructReleaseHistory( Sink sink, ResourceBundle bundle, List releaseList )
 462  
     {
 463  0
         sink.section2();
 464  
 
 465  0
         sinkSectionTitle2Anchor( sink, bundle.getString( "report.changes.label.releasehistory" ),
 466  
                                  bundle.getString( "report.changes.label.releasehistory" ) );
 467  
 
 468  0
         sink.table();
 469  
 
 470  0
         sink.tableRow();
 471  
 
 472  0
         sinkHeader( sink, bundle.getString( "report.issues.label.fixVersion" ) );
 473  
 
 474  0
         sinkHeader( sink, bundle.getString( "report.changes.label.releaseDate" ) );
 475  
 
 476  0
         sinkHeader( sink, bundle.getString( "report.changes.label.releaseDescription" ) );
 477  
 
 478  0
         sink.tableRow_();
 479  
 
 480  0
         for ( int idx = 0; idx < releaseList.size(); idx++ )
 481  
         {
 482  0
             Release release = (Release) releaseList.get( idx );
 483  
 
 484  0
             sink.tableRow();
 485  
 
 486  0
             sinkCellLink( sink, release.getVersion(), "#" + HtmlTools.encodeId( release.getVersion() ) );
 487  
 
 488  0
             sinkCell( sink, release.getDateRelease() );
 489  
 
 490  0
             sinkCell( sink, release.getDescription() );
 491  
 
 492  0
             sink.tableRow_();
 493  
         }
 494  
 
 495  0
         sink.table_();
 496  
 
 497  
         // @todo Temporarily commented out until MCHANGES-46 is completely solved
 498  
         // sink.rawText( bundle.getString( "report.changes.text.rssfeed" ) );
 499  
         // sink.text( " " );
 500  
         // sink.link( "changes.rss" );
 501  
         // sinkFigure( "images/rss.png", sink );
 502  
         // sink.link_();
 503  
         //
 504  
         // sink.lineBreak();
 505  
 
 506  0
         sink.section2_();
 507  0
     }
 508  
 
 509  
     private void constructReleases( Sink sink, ResourceBundle bundle, List releaseList )
 510  
     {
 511  
 
 512  0
         for ( int idx = 0; idx < releaseList.size(); idx++ )
 513  
         {
 514  0
             Release release = (Release) releaseList.get( idx );
 515  
 
 516  0
             sink.section2();
 517  
 
 518  0
             final String date = ( release.getDateRelease() == null ) ? "" : " - " + release.getDateRelease();
 519  
 
 520  0
             sinkSectionTitle2Anchor( sink, bundle.getString( "report.changes.label.release" ) + " "
 521  
                 + release.getVersion() + date, release.getVersion() );
 522  
 
 523  0
             constructActions( sink, release.getActions(), bundle );
 524  
 
 525  0
             sink.section2_();
 526  
         }
 527  0
     }
 528  
 
 529  
     /**
 530  
      * Replace tokens in the issue link template with the real values.
 531  
      *
 532  
      * @param issue The issue identifier
 533  
      * @param system The issue management system
 534  
      * @return An interpolated issue link
 535  
      */
 536  
     private String parseIssueLink( String issue, String system )
 537  
     {
 538  
         String parseLink;
 539  0
         String issueLink = (String) this.issueLinksPerSystem.get( system );
 540  0
         parseLink = issueLink.replaceFirst( ISSUE_TOKEN, issue );
 541  0
         if ( parseLink.indexOf( URL_TOKEN ) >= 0 )
 542  
         {
 543  0
             String url = this.url.substring( 0, this.url.lastIndexOf( "/" ) );
 544  0
             parseLink = parseLink.replaceFirst( URL_TOKEN, url );
 545  
         }
 546  
 
 547  0
         return parseLink;
 548  
     }
 549  
 
 550  
 }