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