View Javadoc

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