Coverage Report - org.apache.maven.report.projectinfo.TeamListReport
 
Classes in this File Line Coverage Branch Coverage Complexity
TeamListReport
100 %
7/7
N/A
4,615
TeamListReport$TeamListRenderer
68 %
140/205
53 %
50/94
4,615
 
 1  
 package org.apache.maven.report.projectinfo;
 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 org.apache.commons.lang.SystemUtils;
 23  
 import org.apache.maven.doxia.sink.Sink;
 24  
 import org.apache.maven.model.Contributor;
 25  
 import org.apache.maven.model.Developer;
 26  
 import org.apache.maven.model.Model;
 27  
 import org.apache.maven.plugin.logging.Log;
 28  
 import org.apache.maven.plugins.annotations.Mojo;
 29  
 import org.codehaus.plexus.i18n.I18N;
 30  
 import org.codehaus.plexus.util.StringUtils;
 31  
 import org.joda.time.DateTimeZone;
 32  
 
 33  
 import java.util.ArrayList;
 34  
 import java.util.HashMap;
 35  
 import java.util.List;
 36  
 import java.util.Locale;
 37  
 import java.util.Map;
 38  
 import java.util.Properties;
 39  
 import java.util.TimeZone;
 40  
 
 41  
 /**
 42  
  * Generates the Project Team report.
 43  
  *
 44  
  * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton </a>
 45  
  * @version $Id: TeamListReport.java 1367255 2012-07-30 20:01:21Z hboutemy $
 46  
  * @since 2.0
 47  
  */
 48  
 @Mojo( name = "project-team" )
 49  1
 public class TeamListReport
 50  
     extends AbstractProjectInfoReport
 51  
 {
 52  
     // ----------------------------------------------------------------------
 53  
     // Public methods
 54  
     // ----------------------------------------------------------------------
 55  
 
 56  
     @Override
 57  
     public void executeReport( Locale locale )
 58  
     {
 59  1
         TeamListRenderer r = new TeamListRenderer( getSink(), project.getModel(), getI18N( locale ), locale, getLog() );
 60  
 
 61  1
         r.render();
 62  1
     }
 63  
 
 64  
     /** {@inheritDoc} */
 65  
     public String getOutputName()
 66  
     {
 67  2
         return "team-list";
 68  
     }
 69  
 
 70  
     @Override
 71  
     protected String getI18Nsection()
 72  
     {
 73  1
         return "team-list";
 74  
     }
 75  
 
 76  
     // ----------------------------------------------------------------------
 77  
     // Private
 78  
     // ----------------------------------------------------------------------
 79  
 
 80  
     /**
 81  
      * Internal renderer class
 82  
      */
 83  1
     private static class TeamListRenderer
 84  
         extends AbstractProjectInfoRenderer
 85  
     {
 86  
         private static final String PROPERTIES = "properties";
 87  
 
 88  
         private static final String TIME_ZONE = "timeZone";
 89  
 
 90  
         private static final String ROLES = "roles";
 91  
 
 92  
         private static final String ORGANIZATION_URL = "organizationUrl";
 93  
 
 94  
         private static final String ORGANIZATION = "organization";
 95  
 
 96  
         private static final String URL = "url";
 97  
 
 98  
         private static final String EMAIL = "email";
 99  
 
 100  
         private static final String NAME = "name";
 101  
 
 102  
         private static final String ID = "id";
 103  
 
 104  
         private final Model model;
 105  
 
 106  
         private final Log log;
 107  
 
 108  1
         private static final String[] EMPTY_STRING_ARRAY = new String[0];
 109  
 
 110  
         TeamListRenderer( Sink sink, Model model, I18N i18n, Locale locale, Log log )
 111  
         {
 112  1
             super( sink, i18n, locale );
 113  
 
 114  1
             this.model = model;
 115  1
             this.log = log;
 116  1
         }
 117  
 
 118  
         @Override
 119  
         protected String getI18Nsection()
 120  
         {
 121  18
             return "team-list";
 122  
         }
 123  
 
 124  
         @Override
 125  
         public void renderBody()
 126  
         {
 127  1
             startSection( getI18nString( "intro.title" ) );
 128  
 
 129  
             // To handle JS
 130  1
             StringBuffer javascript =
 131  
                 new StringBuffer( "function offsetDate(id, offset) {" ).append( SystemUtils.LINE_SEPARATOR );
 132  1
             javascript.append( "    var now = new Date();" ).append( SystemUtils.LINE_SEPARATOR );
 133  1
             javascript.append( "    var nowTime = now.getTime();" ).append( SystemUtils.LINE_SEPARATOR );
 134  1
             javascript.append( "    var localOffset = now.getTimezoneOffset();" ).append( SystemUtils.LINE_SEPARATOR );
 135  1
             javascript.append( "    var developerTime = nowTime + ( offset * 60 * 60 * 1000 )"
 136  
                                    + "+ ( localOffset * 60 * 1000 );" ).append( SystemUtils.LINE_SEPARATOR );
 137  1
             javascript.append( "    var developerDate = new Date(developerTime);" ).append( SystemUtils.LINE_SEPARATOR );
 138  1
             javascript.append( SystemUtils.LINE_SEPARATOR );
 139  1
             javascript.append( "    document.getElementById(id).innerHTML = developerDate;" ).append( SystemUtils.LINE_SEPARATOR );
 140  1
             javascript.append( "}" ).append( SystemUtils.LINE_SEPARATOR );
 141  1
             javascript.append( SystemUtils.LINE_SEPARATOR );
 142  1
             javascript.append( "function init(){" ).append( SystemUtils.LINE_SEPARATOR );
 143  
 
 144  
             // Introduction
 145  1
             paragraph( getI18nString( "intro.description1" ) );
 146  1
             paragraph( getI18nString( "intro.description2" ) );
 147  
 
 148  
             // Developer section
 149  1
             List<Developer> developers = model.getDevelopers();
 150  
 
 151  1
             startSection( getI18nString( "developers.title" ) );
 152  
 
 153  1
             if ( isEmpty( developers ) )
 154  
             {
 155  0
                 paragraph( getI18nString( "nodeveloper" ) );
 156  
             }
 157  
             else
 158  
             {
 159  1
                 paragraph( getI18nString( "developers.intro" ) );
 160  
 
 161  1
                 startTable();
 162  
 
 163  
                 // By default we think that all headers not required: set true for headers that are required
 164  1
                 Map<String, Boolean> headersMap = checkRequiredHeaders( developers );
 165  1
                 String[] requiredHeaders = getRequiredDevHeaderArray( headersMap );
 166  
 
 167  1
                 tableHeader( requiredHeaders );
 168  
 
 169  
                 // To handle JS
 170  1
                 int developersRowId = 0;
 171  1
                 for ( Developer developer : developers )
 172  
                 {
 173  2
                     renderTeamMember( developer, developersRowId, headersMap, javascript );
 174  
 
 175  2
                     developersRowId++;
 176  
                 }
 177  
 
 178  1
                 endTable();
 179  
             }
 180  
 
 181  1
             endSection();
 182  
 
 183  
             // contributors section
 184  1
             List<Contributor> contributors = model.getContributors();
 185  
 
 186  1
             startSection( getI18nString( "contributors.title" ) );
 187  
 
 188  1
             if ( isEmpty( contributors ) )
 189  
             {
 190  1
                 paragraph( getI18nString( "nocontributor" ) );
 191  
             }
 192  
             else
 193  
             {
 194  0
                 paragraph( getI18nString( "contributors.intro" ) );
 195  
 
 196  0
                 startTable();
 197  
 
 198  0
                 Map<String, Boolean> headersMap = checkRequiredHeaders( contributors );
 199  0
                 String[] requiredHeaders = getRequiredContrHeaderArray( headersMap );
 200  
 
 201  0
                 tableHeader( requiredHeaders );
 202  
 
 203  
                 // To handle JS
 204  0
                 int contributorsRowId = 0;
 205  0
                 for ( Contributor contributor : contributors )
 206  
                 {
 207  0
                     renderTeamMember( contributor, contributorsRowId, headersMap, javascript );
 208  
 
 209  0
                     contributorsRowId++;
 210  
                 }
 211  
 
 212  0
                 endTable();
 213  
             }
 214  
 
 215  
             // To handle JS
 216  1
             javascript.append( "}" ).append( SystemUtils.LINE_SEPARATOR ).append( SystemUtils.LINE_SEPARATOR )
 217  
                 .append( "window.onLoad = init();" ).append( SystemUtils.LINE_SEPARATOR );
 218  1
             javaScript( javascript.toString() );
 219  
 
 220  1
             endSection();
 221  
 
 222  1
             endSection();
 223  1
         }
 224  
 
 225  
         private void renderTeamMember( Contributor member, int rowId, Map<String, Boolean> headersMap,
 226  
                                        StringBuffer javascript )
 227  
         {
 228  2
             sink.tableRow();
 229  
 
 230  2
             String type = "contributor";
 231  2
             if ( member instanceof Developer )
 232  
             {
 233  2
                 type = "developer";
 234  2
                 if ( headersMap.get( ID ) == Boolean.TRUE )
 235  
                 {
 236  2
                     String id = ( (Developer) member ).getId();
 237  2
                     if ( id == null )
 238  
                     {
 239  0
                         tableCell( null );
 240  
                     }
 241  
                     else
 242  
                     {
 243  2
                         tableCell( "<a name=\"" + id + "\"></a>" + id, true );
 244  
                     }
 245  
                 }
 246  
             }
 247  2
             if ( headersMap.get( NAME ) == Boolean.TRUE )
 248  
             {
 249  2
                 tableCell( member.getName() );
 250  
             }
 251  2
             if ( headersMap.get( EMAIL ) == Boolean.TRUE )
 252  
             {
 253  2
                 tableCell( createLinkPatternedText( member.getEmail(), member.getEmail() ) );
 254  
             }
 255  2
             if ( headersMap.get( URL ) == Boolean.TRUE )
 256  
             {
 257  0
                 tableCellForUrl( member.getUrl() );
 258  
             }
 259  2
             if ( headersMap.get( ORGANIZATION ) == Boolean.TRUE )
 260  
             {
 261  2
                 tableCell( member.getOrganization() );
 262  
             }
 263  2
             if ( headersMap.get( ORGANIZATION_URL ) == Boolean.TRUE )
 264  
             {
 265  0
                 tableCellForUrl( member.getOrganizationUrl() );
 266  
             }
 267  2
             if ( headersMap.get( ROLES ) == Boolean.TRUE )
 268  
             {
 269  2
                 if ( member.getRoles() != null )
 270  
                 {
 271  
                     // Comma separated roles
 272  2
                     tableCell( StringUtils.join( member.getRoles().toArray( EMPTY_STRING_ARRAY ), ", " ) );
 273  
                 }
 274  
                 else
 275  
                 {
 276  0
                     tableCell( null );
 277  
                 }
 278  
             }
 279  2
             if ( headersMap.get( TIME_ZONE ) == Boolean.TRUE )
 280  
             {
 281  2
                 tableCell( member.getTimezone() );
 282  
 
 283  2
                 if ( StringUtils.isNotEmpty( member.getTimezone() )
 284  
                     && ( !ProjectInfoReportUtils.isNumber( member.getTimezone().trim() ) ) )
 285  
                 {
 286  0
                     String tz = member.getTimezone().trim();
 287  
                     try
 288  
                     {
 289  
                         // check if it is a valid timeZone
 290  0
                         DateTimeZone.forID( tz );
 291  
 
 292  0
                         sink.tableCell();
 293  0
                         sink.rawText( "<span id=\"" + type + "-" + rowId + "\">" );
 294  0
                         text( tz );
 295  0
                         String offSet = String.valueOf( TimeZone.getTimeZone( tz ).getRawOffset() / 3600000 );
 296  0
                         javascript.append( "    offsetDate('" ).append( type ).append( "-" ).append( rowId ).append( "', '" );
 297  0
                         javascript.append( offSet ).append( "');" ).append( SystemUtils.LINE_SEPARATOR );
 298  0
                         sink.rawText( "</span>" );
 299  0
                         sink.tableCell_();
 300  
                     }
 301  0
                     catch ( IllegalArgumentException e )
 302  
                     {
 303  0
                         log.warn( "The time zone '" + tz + "' for the " + type + " '" + member.getName()
 304  
                             + "' is not a recognised time zone, use a number in the range -12 and +14 instead of." );
 305  
 
 306  0
                         sink.tableCell();
 307  0
                         sink.rawText( "<span id=\"" + type + "-" + rowId + "\">" );
 308  0
                         text( null );
 309  0
                         sink.rawText( "</span>" );
 310  0
                         sink.tableCell_();
 311  0
                     }
 312  0
                 }
 313  
                 else
 314  
                 {
 315  
                     // To handle JS
 316  2
                     sink.tableCell();
 317  2
                     sink.rawText( "<span id=\"" + type + "-" + rowId + "\">" );
 318  2
                     if ( StringUtils.isEmpty( member.getTimezone() ) )
 319  
                     {
 320  0
                         text( null );
 321  
                     }
 322  
                     else
 323  
                     {
 324  
                         // check if number is between -12 and +14
 325  2
                         float tz = ProjectInfoReportUtils.toFloat( member.getTimezone().trim(), Integer.MIN_VALUE );
 326  2
                         if ( tz == Integer.MIN_VALUE || !( tz >= -12 && tz <= 14 ) )
 327  
                         {
 328  0
                             text( null );
 329  0
                             log.warn( "The time zone '" + member.getTimezone().trim() + "' for the " + type + " '"
 330  
                                 + member.getName()
 331  
                                 + "' is not a recognised time zone, use a number in the range -12 to +14 instead of." );
 332  
                         }
 333  
                         else
 334  
                         {
 335  2
                             text( member.getTimezone().trim() );
 336  2
                             javascript.append( "    offsetDate('" ).append( type ).append( "-" ).append( rowId ).append( "', '" );
 337  2
                             javascript.append( member.getTimezone() ).append( "');" ).append( SystemUtils.LINE_SEPARATOR );
 338  
                         }
 339  
                     }
 340  2
                     sink.rawText( "</span>" );
 341  2
                     sink.tableCell_();
 342  
                 }
 343  
             }
 344  
 
 345  2
             if ( headersMap.get( PROPERTIES ) == Boolean.TRUE )
 346  
             {
 347  0
                 Properties props = member.getProperties();
 348  0
                 if ( props != null )
 349  
                 {
 350  0
                     tableCell( propertiesToString( props ) );
 351  
                 }
 352  
                 else
 353  
                 {
 354  0
                     tableCell( null );
 355  
                 }
 356  
             }
 357  
 
 358  2
             sink.tableRow_();
 359  2
         }
 360  
 
 361  
         /**
 362  
          * @param requiredHeaders
 363  
          * @return
 364  
          */
 365  
         private String[] getRequiredContrHeaderArray( Map<String, Boolean> requiredHeaders )
 366  
         {
 367  0
             List<String> requiredArray = new ArrayList<String>();
 368  0
             String name = getI18nString( "contributors.name" );
 369  0
             String email = getI18nString( "contributors.email" );
 370  0
             String url = getI18nString( "contributors.url" );
 371  0
             String organization = getI18nString( "contributors.organization" );
 372  0
             String organizationUrl = getI18nString( "contributors.organizationurl" );
 373  0
             String roles = getI18nString( "contributors.roles" );
 374  0
             String timeZone = getI18nString( "contributors.timezone" );
 375  0
             String actualTime = getI18nString( "contributors.actualtime" );
 376  0
             String properties = getI18nString( "contributors.properties" );
 377  
 
 378  0
             setRequiredArray( requiredHeaders, requiredArray, name, email, url, organization, organizationUrl, roles,
 379  
                               timeZone, actualTime, properties );
 380  
 
 381  0
             return requiredArray.toArray( new String[requiredArray.size()] );
 382  
         }
 383  
 
 384  
         /**
 385  
          * @param requiredHeaders
 386  
          * @return
 387  
          */
 388  
         private String[] getRequiredDevHeaderArray( Map<String, Boolean> requiredHeaders )
 389  
         {
 390  1
             List<String> requiredArray = new ArrayList<String>();
 391  
 
 392  1
             String id = getI18nString( "developers.id" );
 393  1
             String name = getI18nString( "developers.name" );
 394  1
             String email = getI18nString( "developers.email" );
 395  1
             String url = getI18nString( "developers.url" );
 396  1
             String organization = getI18nString( "developers.organization" );
 397  1
             String organizationUrl = getI18nString( "developers.organizationurl" );
 398  1
             String roles = getI18nString( "developers.roles" );
 399  1
             String timeZone = getI18nString( "developers.timezone" );
 400  1
             String actualTime = getI18nString( "developers.actualtime" );
 401  1
             String properties = getI18nString( "developers.properties" );
 402  
 
 403  1
             if ( requiredHeaders.get( ID ) == Boolean.TRUE )
 404  
             {
 405  1
                 requiredArray.add( id );
 406  
             }
 407  
 
 408  1
             setRequiredArray( requiredHeaders, requiredArray, name, email, url, organization, organizationUrl, roles,
 409  
                               timeZone, actualTime, properties );
 410  
 
 411  1
             return requiredArray.toArray( new String[requiredArray.size()] );
 412  
         }
 413  
 
 414  
         /**
 415  
          * @param requiredHeaders
 416  
          * @param requiredArray
 417  
          * @param name
 418  
          * @param email
 419  
          * @param url
 420  
          * @param organization
 421  
          * @param organizationUrl
 422  
          * @param roles
 423  
          * @param timeZone
 424  
          * @param actualTime
 425  
          * @param properties
 426  
          */
 427  
         private void setRequiredArray( Map<String, Boolean> requiredHeaders, List<String> requiredArray, String name,
 428  
                                        String email, String url, String organization, String organizationUrl,
 429  
                                        String roles, String timeZone, String actualTime, String properties )
 430  
         {
 431  1
             if ( requiredHeaders.get( NAME ) == Boolean.TRUE )
 432  
             {
 433  1
                 requiredArray.add( name );
 434  
             }
 435  1
             if ( requiredHeaders.get( EMAIL ) == Boolean.TRUE )
 436  
             {
 437  1
                 requiredArray.add( email );
 438  
             }
 439  1
             if ( requiredHeaders.get( URL ) == Boolean.TRUE )
 440  
             {
 441  0
                 requiredArray.add( url );
 442  
             }
 443  1
             if ( requiredHeaders.get( ORGANIZATION ) == Boolean.TRUE )
 444  
             {
 445  1
                 requiredArray.add( organization );
 446  
             }
 447  1
             if ( requiredHeaders.get( ORGANIZATION_URL ) == Boolean.TRUE )
 448  
             {
 449  0
                 requiredArray.add( organizationUrl );
 450  
             }
 451  1
             if ( requiredHeaders.get( ROLES ) == Boolean.TRUE )
 452  
             {
 453  1
                 requiredArray.add( roles );
 454  
             }
 455  1
             if ( requiredHeaders.get( TIME_ZONE ) == Boolean.TRUE )
 456  
             {
 457  1
                 requiredArray.add( timeZone );
 458  1
                 requiredArray.add( actualTime );
 459  
             }
 460  
 
 461  1
             if ( requiredHeaders.get( PROPERTIES ) == Boolean.TRUE )
 462  
             {
 463  0
                 requiredArray.add( properties );
 464  
             }
 465  1
         }
 466  
 
 467  
         /**
 468  
          * @param units contributors and developers to check
 469  
          * @return required headers
 470  
          */
 471  
         private Map<String, Boolean> checkRequiredHeaders( List<? extends Contributor> units )
 472  
         {
 473  1
             Map<String, Boolean> requiredHeaders = new HashMap<String, Boolean>();
 474  
 
 475  1
             requiredHeaders.put( ID, Boolean.FALSE );
 476  1
             requiredHeaders.put( NAME, Boolean.FALSE );
 477  1
             requiredHeaders.put( EMAIL, Boolean.FALSE );
 478  1
             requiredHeaders.put( URL, Boolean.FALSE );
 479  1
             requiredHeaders.put( ORGANIZATION, Boolean.FALSE );
 480  1
             requiredHeaders.put( ORGANIZATION_URL, Boolean.FALSE );
 481  1
             requiredHeaders.put( ROLES, Boolean.FALSE );
 482  1
             requiredHeaders.put( TIME_ZONE, Boolean.FALSE );
 483  1
             requiredHeaders.put( PROPERTIES, Boolean.FALSE );
 484  
 
 485  1
             for ( Contributor unit : units )
 486  
             {
 487  2
                 if ( unit instanceof Developer )
 488  
                 {
 489  2
                     Developer developer = (Developer) unit;
 490  2
                     if ( StringUtils.isNotEmpty( developer.getId() ) )
 491  
                     {
 492  2
                         requiredHeaders.put( ID, Boolean.TRUE );
 493  
                     }
 494  
                 }
 495  2
                 if ( StringUtils.isNotEmpty( unit.getName() ) )
 496  
                 {
 497  2
                     requiredHeaders.put( NAME, Boolean.TRUE );
 498  
                 }
 499  2
                 if ( StringUtils.isNotEmpty( unit.getEmail() ) )
 500  
                 {
 501  1
                     requiredHeaders.put( EMAIL, Boolean.TRUE );
 502  
                 }
 503  2
                 if ( StringUtils.isNotEmpty( unit.getUrl() ) )
 504  
                 {
 505  0
                     requiredHeaders.put( URL, Boolean.TRUE );
 506  
                 }
 507  2
                 if ( StringUtils.isNotEmpty( unit.getOrganization() ) )
 508  
                 {
 509  1
                     requiredHeaders.put( ORGANIZATION, Boolean.TRUE );
 510  
                 }
 511  2
                 if ( StringUtils.isNotEmpty( unit.getOrganizationUrl() ) )
 512  
                 {
 513  0
                     requiredHeaders.put( ORGANIZATION_URL, Boolean.TRUE );
 514  
                 }
 515  2
                 if ( !isEmpty( unit.getRoles() ) )
 516  
                 {
 517  1
                     requiredHeaders.put( ROLES, Boolean.TRUE );
 518  
                 }
 519  2
                 if ( StringUtils.isNotEmpty( unit.getTimezone() ) )
 520  
                 {
 521  2
                     requiredHeaders.put( TIME_ZONE, Boolean.TRUE );
 522  
                 }
 523  2
                 Properties properties = unit.getProperties();
 524  2
                 if ( null != properties && !properties.isEmpty() )
 525  
                 {
 526  0
                     requiredHeaders.put( PROPERTIES, Boolean.TRUE );
 527  
                 }
 528  2
             }
 529  1
             return requiredHeaders;
 530  
         }
 531  
 
 532  
         /**
 533  
          * Create a table cell with a link to the given url. The url is not validated.
 534  
          *
 535  
          * @param url
 536  
          */
 537  
         private void tableCellForUrl( String url )
 538  
         {
 539  0
             sink.tableCell();
 540  
 
 541  0
             if ( StringUtils.isEmpty( url ) )
 542  
             {
 543  0
                 text( url );
 544  
             }
 545  
             else
 546  
             {
 547  0
                 link( url, url );
 548  
             }
 549  
 
 550  0
             sink.tableCell_();
 551  0
         }
 552  
 
 553  
         private boolean isEmpty( List<?> list )
 554  
         {
 555  4
             return ( list == null ) || list.isEmpty();
 556  
         }
 557  
     }
 558  
 }