Coverage Report - org.apache.maven.changelog.DeveloperActivityReport
 
Classes in this File Line Coverage Branch Coverage Complexity
DeveloperActivityReport
96% 
100% 
2
 
 1  
 package org.apache.maven.changelog;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2006 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *      http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import org.apache.maven.model.Developer;
 20  
 import org.apache.maven.scm.ChangeFile;
 21  
 import org.apache.maven.scm.ChangeSet;
 22  
 import org.apache.maven.scm.command.changelog.ChangeLogSet;
 23  
 import org.codehaus.doxia.sink.Sink;
 24  
 
 25  
 import java.util.Collection;
 26  
 import java.util.HashMap;
 27  
 import java.util.Iterator;
 28  
 import java.util.LinkedList;
 29  
 import java.util.List;
 30  
 import java.util.Locale;
 31  
 import java.util.ResourceBundle;
 32  
 
 33  
 /**
 34  
  * Generate a developer activity report.
 35  
  *
 36  
  * @goal dev-activity
 37  
  */
 38  10
 public class DeveloperActivityReport
 39  
     extends ChangeLogReport
 40  
 {
 41  
     /**
 42  
      * List of developers to be shown on the report.
 43  
      *
 44  
      * @parameter expression="${project.developers}"
 45  
      */
 46  
     private List developers;
 47  
 
 48  
     /**
 49  
      * Used to hold data while creating the report
 50  
      */
 51  
     private HashMap commits;
 52  
 
 53  
     private HashMap files;
 54  
 
 55  
     /**
 56  
      * @see org.apache.maven.reporting.MavenReport#getDescription(java.util.Locale)
 57  
      */
 58  
     public String getDescription( Locale locale )
 59  
     {
 60  0
         return "Generated developer activity report from SCM.";
 61  
     }
 62  
 
 63  
     /**
 64  
      * @see org.apache.maven.reporting.MavenReport#getName(java.util.Locale)
 65  
      */
 66  
     public String getName( Locale locale )
 67  
     {
 68  10
         return "Developer Activity";
 69  
     }
 70  
 
 71  
     /**
 72  
      * @see org.apache.maven.reporting.MavenReport#getOutputName()
 73  
      */
 74  
     public String getOutputName()
 75  
     {
 76  20
         return "dev-activity";
 77  
     }
 78  
 
 79  
     /**
 80  
      * generates an empty report in case there are no sources to generate a report with
 81  
      *
 82  
      * @param bundle the resource bundle to retrieve report phrases from
 83  
      * @param sink   the report formatting tool
 84  
      */
 85  
     protected void doGenerateEmptyReport( ResourceBundle bundle, Sink sink )
 86  
     {
 87  5
         sink.head();
 88  5
         sink.title();
 89  5
         sink.text( bundle.getString( "report.dev-activity.header" ) );
 90  5
         sink.title_();
 91  5
         sink.head_();
 92  
 
 93  5
         sink.body();
 94  5
         sink.section1();
 95  
 
 96  5
         sink.sectionTitle1();
 97  5
         sink.text( bundle.getString( "report.dev-activity.mainTitle" ) );
 98  5
         sink.sectionTitle1_();
 99  
 
 100  5
         sink.paragraph();
 101  5
         sink.text( "No sources found to create a report." );
 102  5
         sink.paragraph_();
 103  
 
 104  5
         sink.section1_();
 105  
 
 106  5
         sink.body_();
 107  5
         sink.flush();
 108  5
         sink.close();
 109  5
     }
 110  
 
 111  
     /**
 112  
      * method that generates the report for this mojo.
 113  
      *
 114  
      * @param changeLogSets changed sets to generate the report from
 115  
      * @param bundle        the resource bundle to retrieve report phrases from
 116  
      * @param sink          the report formatting tool
 117  
      */
 118  
     protected void doGenerateReport( List changeLogSets, ResourceBundle bundle, Sink sink )
 119  
     {
 120  5
         sink.head();
 121  5
         sink.title();
 122  5
         sink.text( bundle.getString( "report.dev-activity.header" ) );
 123  5
         sink.title_();
 124  5
         sink.head_();
 125  
 
 126  5
         sink.body();
 127  5
         sink.section1();
 128  5
         sink.sectionTitle1();
 129  5
         sink.text( bundle.getString( "report.dev-activity.mainTitle" ) );
 130  5
         sink.sectionTitle1_();
 131  
 
 132  5
         for ( Iterator sets = changeLogSets.iterator(); sets.hasNext(); )
 133  
         {
 134  10
             ChangeLogSet set = (ChangeLogSet) sets.next();
 135  10
             doChangedSets( set, bundle, sink );
 136  
         }
 137  
 
 138  5
         sink.section1_();
 139  5
         sink.body_();
 140  5
         sink.flush();
 141  5
         sink.table_();
 142  5
     }
 143  
 
 144  
     /**
 145  
      * generates a section of the report referring to a changeset
 146  
      *
 147  
      * @param set    the current ChangeSet to generate this section of the report
 148  
      * @param bundle the resource bundle to retrieve report phrases from
 149  
      * @param sink   the report formatting tool
 150  
      */
 151  
     private void doChangedSets( ChangeLogSet set, ResourceBundle bundle, Sink sink )
 152  
     {
 153  10
         sink.section2();
 154  10
         sink.sectionTitle2();
 155  10
         if ( set.getStartDate() == null )
 156  
         {
 157  0
             sink.text( bundle.getString( "report.SetRangeUnknown" ) );
 158  
         }
 159  10
         else if ( set.getEndDate() == null )
 160  
         {
 161  0
             sink.text( bundle.getString( "report.SetRangeSince" ) );
 162  
         }
 163  
         else
 164  
         {
 165  10
             sink.text( " " + set.getStartDate() + " " + bundle.getString( "report.To" ) + " " + set.getEndDate() );
 166  10
             sink.sectionTitle2_();
 167  
         }
 168  10
         doSummary( set, bundle, sink );
 169  
 
 170  10
         sink.table();
 171  
 
 172  10
         sink.tableRow();
 173  10
         sink.tableHeaderCell();
 174  10
         sink.text( bundle.getString( "report.dev-activity.developer" ) );
 175  10
         sink.tableHeaderCell_();
 176  10
         sink.tableHeaderCell();
 177  10
         sink.text( bundle.getString( "report.TotalCommits" ) );
 178  10
         sink.tableHeaderCell_();
 179  10
         sink.tableHeaderCell();
 180  10
         sink.text( bundle.getString( "report.dev-activity.filesChanged" ) );
 181  10
         sink.tableHeaderCell_();
 182  10
         sink.tableRow_();
 183  
 
 184  10
         doDeveloperRows( set, sink );
 185  
 
 186  10
         sink.table_();
 187  
 
 188  10
         sink.section2_();
 189  10
     }
 190  
 
 191  
     /**
 192  
      * generates the report summary section of the report
 193  
      *
 194  
      * @param set    changed set to generate the report from
 195  
      * @param bundle the resource bundle to retrieve report phrases from
 196  
      * @param sink   the report formatting tool
 197  
      */
 198  
     private void doSummary( ChangeLogSet set, ResourceBundle bundle, Sink sink )
 199  
     {
 200  10
         sink.paragraph();
 201  
 
 202  10
         sink.text( bundle.getString( "report.dev-activity.range" ) );
 203  10
         sink.text( ": " + set.getStartDate() + " " + bundle.getString( "report.To" ) + " " + set.getEndDate() );
 204  
 
 205  10
         sink.text( ", " + bundle.getString( "report.TotalCommits" ) );
 206  10
         sink.text( ":" + set.getChangeSets().size() );
 207  
 
 208  10
         sink.text( ", " + bundle.getString( "report.dev-activity.filesChanged" ) );
 209  10
         sink.text( ":" + countFilesChanged( set.getChangeSets() ) );
 210  
 
 211  10
         sink.paragraph_();
 212  10
     }
 213  
 
 214  
     /**
 215  
      * generates the report section table of the developers
 216  
      *
 217  
      * @param set  change log set generate the developer activity
 218  
      * @param sink the report formatting tool
 219  
      */
 220  
     private void doDeveloperRows( ChangeLogSet set, Sink sink )
 221  
     {
 222  10
         initDeveloperDetails( set );
 223  
 
 224  
         //for( Iterator i=commits.keySet().iterator(); i.hasNext(); )
 225  10
         for ( Iterator i = developers.iterator(); i.hasNext(); )
 226  
         {
 227  20
             Developer developer = (Developer) i.next();
 228  
 
 229  20
             String name = developer.getName();
 230  
 
 231  20
             String id = developer.getId();
 232  
 
 233  
             LinkedList devCommits;
 234  
             HashMap devFiles;
 235  
 
 236  20
             if ( !commits.containsKey( name ) )
 237  
             {
 238  10
                 if ( !commits.containsKey( id ) )
 239  
                 {
 240  10
                     continue;
 241  
                 }
 242  
                 else
 243  
                 {
 244  0
                     devCommits = (LinkedList) commits.get( id );
 245  
 
 246  0
                     devFiles = (HashMap) files.get( id );
 247  
                 }
 248  
             }
 249  
             else
 250  
             {
 251  10
                 devCommits = (LinkedList) commits.get( name );
 252  
 
 253  10
                 devFiles = (HashMap) files.get( name );
 254  
             }
 255  
 
 256  10
             sink.tableRow();
 257  
 
 258  10
             sink.tableCell();
 259  10
             sink.link( "team-list.html#" + developer.getId() );
 260  10
             sink.text( name );
 261  10
             sink.link_();
 262  10
             sink.tableCell_();
 263  
 
 264  10
             sink.tableCell();
 265  10
             sink.text( "" + devCommits.size() );
 266  10
             sink.tableCell_();
 267  
 
 268  10
             sink.tableCell();
 269  10
             sink.text( "" + devFiles.size() );
 270  10
             sink.tableCell_();
 271  
 
 272  10
             sink.tableRow_();
 273  
         }
 274  10
     }
 275  
 
 276  
     /**
 277  
      * counts the number of commits and files changed for each developer
 278  
      *
 279  
      * @param set the change log set to generate the developer details from
 280  
      */
 281  
     private void initDeveloperDetails( ChangeLogSet set )
 282  
     {
 283  10
         commits = new HashMap();
 284  
 
 285  10
         files = new HashMap();
 286  
 
 287  10
         countDevCommits( set.getChangeSets() );
 288  
 
 289  10
         countDevFiles( set.getChangeSets() );
 290  10
     }
 291  
 
 292  
     /**
 293  
      * counts the number of commits of each developer
 294  
      *
 295  
      * @param entries the change log entries used to search and count developer commits
 296  
      */
 297  
     private void countDevCommits( Collection entries )
 298  
     {
 299  10
         for ( Iterator i = entries.iterator(); i.hasNext(); )
 300  
         {
 301  20
             ChangeSet entry = (ChangeSet) i.next();
 302  
 
 303  20
             String developer = entry.getAuthor();
 304  
 
 305  
             LinkedList list;
 306  
 
 307  20
             if ( commits.containsKey( developer ) )
 308  
             {
 309  10
                 list = (LinkedList) commits.get( developer );
 310  
             }
 311  
             else
 312  
             {
 313  10
                 list = new LinkedList();
 314  
             }
 315  
 
 316  20
             list.add( entry );
 317  
 
 318  20
             commits.put( developer, list );
 319  
         }
 320  10
     }
 321  
 
 322  
     /**
 323  
      * counts the number of files changed by each developer
 324  
      *
 325  
      * @param entries the change log entries used to search and count file changes
 326  
      */
 327  
     private void countDevFiles( Collection entries )
 328  
     {
 329  10
         for ( Iterator i2 = entries.iterator(); i2.hasNext(); )
 330  
         {
 331  20
             ChangeSet entry = (ChangeSet) i2.next();
 332  
 
 333  20
             String developer = entry.getAuthor();
 334  
 
 335  
             HashMap filesMap;
 336  
 
 337  20
             if ( files.containsKey( developer ) )
 338  
             {
 339  10
                 filesMap = (HashMap) files.get( developer );
 340  
             }
 341  
             else
 342  
             {
 343  10
                 filesMap = new HashMap();
 344  
             }
 345  
 
 346  20
             for ( Iterator i3 = entry.getFiles().iterator(); i3.hasNext(); )
 347  
             {
 348  30
                 ChangeFile file = (ChangeFile) i3.next();
 349  
 
 350  30
                 filesMap.put( file.getName(), file );
 351  
             }
 352  
 
 353  20
             files.put( developer, filesMap );
 354  
         }
 355  10
     }
 356  
 }