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