KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > maven > reporting > AbstractMavenReportRenderer


1 package org.apache.maven.reporting;
2
3 /*
4  * Copyright 2001-2005 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import org.apache.commons.validator.EmailValidator;
20 import org.apache.commons.validator.UrlValidator;
21 import org.apache.maven.doxia.sink.Sink;
22 import org.codehaus.plexus.util.StringUtils;
23
24 import java.util.Collections JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.LinkedHashMap JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Properties JavaDoc;
29
30 /**
31  * An abstract class to manage report generation.
32  *
33  * @author <a HREF="mailto:jason@maven.org">Jason van Zyl</a>
34  * @author <a HREF="evenisse@apache.org">Emmanuel Venisse</a>
35  * @author <a HREF="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
36  * @version $Id: AbstractMavenReportRenderer.java 163373 2005-02-22 03:37:00Z brett $
37  * @todo Later it may be appropriate to create something like a VelocityMavenReportRenderer that could take a velocity template and pipe that through Doxia rather than coding them up like this.
38  */

39 public abstract class AbstractMavenReportRenderer
40     implements MavenReportRenderer
41 {
42     protected Sink sink;
43
44     private int section;
45
46     public AbstractMavenReportRenderer( Sink sink )
47     {
48         this.sink = sink;
49     }
50
51     public void render()
52     {
53         sink.head();
54
55         sink.title();
56
57         text( getTitle() );
58
59         sink.title_();
60
61         sink.head_();
62
63         sink.body();
64
65         renderBody();
66
67         sink.body_();
68
69         sink.flush();
70
71         sink.close();
72     }
73
74     protected void startTable()
75     {
76         sink.table();
77     }
78
79     protected void endTable()
80     {
81         sink.table_();
82     }
83
84     protected void startSection( String JavaDoc name )
85     {
86         section = section + 1;
87
88         switch ( section )
89         {
90             case 1:
91                 sink.section1();
92                 sink.sectionTitle1();
93                 break;
94             case 2:
95                 sink.section2();
96                 sink.sectionTitle2();
97                 break;
98             case 3:
99                 sink.section3();
100                 sink.sectionTitle3();
101                 break;
102             case 4:
103                 sink.section4();
104                 sink.sectionTitle4();
105                 break;
106             case 5:
107                 sink.section5();
108                 sink.sectionTitle5();
109                 break;
110
111             default:
112                 // TODO: warning - just don't start a section
113
break;
114         }
115
116         text( name );
117
118         switch ( section )
119         {
120             case 1:
121                 sink.sectionTitle1_();
122                 break;
123             case 2:
124                 sink.sectionTitle2_();
125                 break;
126             case 3:
127                 sink.sectionTitle3_();
128                 break;
129             case 4:
130                 sink.sectionTitle4_();
131                 break;
132             case 5:
133                 sink.sectionTitle5_();
134                 break;
135
136             default:
137                 // TODO: warning - just don't start a section
138
break;
139         }
140     }
141
142     protected void endSection()
143     {
144         switch ( section )
145         {
146             case 1:
147                 sink.section1_();
148                 break;
149             case 2:
150                 sink.section2_();
151                 break;
152             case 3:
153                 sink.section3_();
154                 break;
155             case 4:
156                 sink.section4_();
157                 break;
158             case 5:
159                 sink.section5_();
160                 break;
161
162             default:
163                 // TODO: warning - just don't start a section
164
break;
165         }
166
167         section = section - 1;
168
169         if ( section < 0 )
170         {
171             throw new IllegalStateException JavaDoc( "Too many closing sections" );
172         }
173     }
174
175     protected void tableHeaderCell( String JavaDoc text )
176     {
177         sink.tableHeaderCell();
178
179         text( text );
180
181         sink.tableHeaderCell_();
182     }
183
184     /**
185      * Add a cell in a table.
186      * <p>The text could be a link patterned text defined by <code>{text, url}</code></p>
187      *
188      * @param text
189      * @see #linkPatternedText(String)
190      */

191     protected void tableCell( String JavaDoc text )
192     {
193         tableCell( text, false );
194     }
195
196     /**
197      * Add a cell in a table.
198      * <p>If <code>asHtml</code> is true, add the text as Html</p>
199      *
200      * @param text
201      * @param asHtml
202      */

203     protected void tableCell( String JavaDoc text, boolean asHtml )
204     {
205         sink.tableCell();
206
207         if ( asHtml )
208         {
209             sink.rawText( text );
210         }
211         else
212         {
213             linkPatternedText( text );
214         }
215
216         sink.tableCell_();
217     }
218
219     protected void tableRow( String JavaDoc[] content )
220     {
221         sink.tableRow();
222
223         for ( int i = 0; i < content.length; i++ )
224         {
225             tableCell( content[i] );
226         }
227
228         sink.tableRow_();
229     }
230
231     protected void tableHeader( String JavaDoc[] content )
232     {
233         sink.tableRow();
234
235         for ( int i = 0; i < content.length; i++ )
236         {
237             tableHeaderCell( content[i] );
238         }
239
240         sink.tableRow_();
241     }
242
243     protected void tableCaption( String JavaDoc caption )
244     {
245         sink.tableCaption();
246
247         text( caption );
248
249         sink.tableCaption_();
250     }
251
252     protected void paragraph( String JavaDoc paragraph )
253     {
254         sink.paragraph();
255
256         text( paragraph );
257
258         sink.paragraph_();
259     }
260
261     protected void link( String JavaDoc href, String JavaDoc name )
262     {
263         sink.link( href );
264
265         text( name );
266
267         sink.link_();
268     }
269
270     /**
271      * Add a new text.
272      * <p>If text is empty of has a null value, add the "-" charater</p>
273      *
274      * @param text a string
275      */

276     protected void text( String JavaDoc text )
277     {
278         if ( text == null || text.length() == 0 ) // Take care of spaces
279
{
280             sink.text( "-" );
281         }
282         else
283         {
284             sink.text( text );
285         }
286     }
287
288     /**
289      * Add a verbatim text.
290      *
291      * @param text a string
292      * @see #text(String)
293      */

294     protected void verbatimText( String JavaDoc text )
295     {
296         sink.verbatim( true );
297
298         text( text );
299
300         sink.verbatim_();
301     }
302
303     /**
304      * Add a verbatim text with a specific link.
305      *
306      * @param text a string
307      * @param href an href could be null
308      * @see #link(String, String)
309      */

310     protected void verbatimLink( String JavaDoc text, String JavaDoc href )
311     {
312         if ( StringUtils.isEmpty( href ) )
313         {
314             verbatimText( text );
315         }
316         else
317         {
318             sink.verbatim( true );
319
320             link( href, text );
321
322             sink.verbatim_();
323         }
324     }
325
326     /**
327      * Add a Javascript code.
328      *
329      * @param jsCode a string of Javascript
330      */

331     protected void javaScript( String JavaDoc jsCode )
332     {
333         sink.rawText( "<script type=\"text/javascript\">\n" + jsCode + "</script>" );
334     }
335
336     /**
337      * Add a text with links inside.
338      * <p>The text variable should contained this given pattern <code>{text, url}</code>
339      * to handle the link creation.</p>
340      *
341      * @param text a text with link pattern defined.
342      * @see #text(String)
343      * @see #applyPattern(String)
344      */

345     public void linkPatternedText( String JavaDoc text )
346     {
347         if ( StringUtils.isEmpty( text ) )
348         {
349             text( text );
350         }
351         else
352         {
353             Map JavaDoc segments = applyPattern( text );
354
355             if ( segments == null )
356             {
357                 text( text );
358             }
359             else
360             {
361                 for ( Iterator JavaDoc it = segments.entrySet().iterator(); it.hasNext(); )
362                 {
363                     Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
364
365                     String JavaDoc name = (String JavaDoc) entry.getKey();
366                     String JavaDoc href = (String JavaDoc) entry.getValue();
367
368                     if ( href == null )
369                     {
370                         text( name );
371                     }
372                     else
373                     {
374                         if ( getValidHref( href ) != null )
375                         {
376                             link( getValidHref( href ), name );
377                         }
378                         else
379                         {
380                             text( href );
381                         }
382                     }
383                 }
384             }
385         }
386     }
387
388     /**
389      * Create a link pattern text defined by <code>{text, url}</code>.
390      * <p>This created pattern could be used by the method <code>linkPatternedText(String)</code> to
391      * handle a text with link.</p>
392      *
393      * @param text
394      * @param href
395      * @return a link pattern
396      * @see #linkPatternedText(String)
397      */

398     protected static String JavaDoc createLinkPatternedText( String JavaDoc text, String JavaDoc href )
399     {
400         if ( text == null )
401         {
402             return text;
403         }
404
405         if ( href == null )
406         {
407             return text;
408         }
409
410         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
411         sb.append( "{" ).append( text ).append( ", " ).append( href ).append( "}" );
412
413         return sb.toString();
414     }
415
416     /**
417      * Convenience method to display a <code>Properties</code> object comma separated.
418      *
419      * @param props
420      * @return the properties object as comma separated String
421      */

422     protected static String JavaDoc propertiesToString( Properties JavaDoc props )
423     {
424         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
425
426         if ( props == null || props.isEmpty() )
427         {
428             return sb.toString();
429         }
430
431         for ( Iterator JavaDoc i = props.keySet().iterator(); i.hasNext(); )
432         {
433             String JavaDoc key = (String JavaDoc) i.next();
434             sb.append( key ).append( "=" ).append( props.get( key ) );
435             if ( i.hasNext() )
436             {
437                 sb.append( ", " );
438             }
439         }
440
441         return sb.toString();
442     }
443
444     /**
445      * Return a valid href.
446      * <p>A valid href could start by <code>mailto:</code>.</p>
447      * <p>For a relative path, the href should start by <code>./</code> to be valid.</p>
448      *
449      * @param href an href
450      * @return a valid href or null if the href is not valid.
451      */

452     private static String JavaDoc getValidHref( String JavaDoc href )
453     {
454         href = href.trim();
455
456         String JavaDoc[] schemes = {"http", "https"};
457         UrlValidator urlValidator = new UrlValidator( schemes );
458
459         if ( ( EmailValidator.getInstance().isValid( href ) ) ||
460              ( ( href.indexOf( "?" ) != -1 ) &&
461                ( EmailValidator.getInstance().isValid( href.substring( 0, href.indexOf( "?" ) ) ) ) ) )
462         {
463             return "mailto:" + href;
464         }
465         else if ( href.toLowerCase().startsWith( "mailto:" ) )
466         {
467             return href;
468         }
469         else if ( urlValidator.isValid( href ) )
470         {
471             return href;
472         }
473         else
474         {
475             // TODO Waiting for new release of Validator
476
// http://issues.apache.org/bugzilla/show_bug.cgi?id=30686
477
String JavaDoc hrefTmp;
478             if ( !href.endsWith( "/" ) )
479             {
480                 hrefTmp = href + "/index.html";
481             }
482             else
483             {
484                 hrefTmp = href + "index.html";
485             }
486
487             if ( urlValidator.isValid( hrefTmp ) )
488             {
489                 return href;
490             }
491
492             if ( href.startsWith( "./" ) )
493             {
494                 if ( href.length() > 2 )
495                 {
496                     return href.substring(2, href.length() );
497                 }
498                 else
499                 {
500                     return ".";
501                 }
502             }
503
504             return null;
505         }
506     }
507
508     /**
509      * The method parses a text an apply the given pattern <code>{text, url}</code> to create
510      * a map of text/href.
511      *
512      * @param text a text with or without the pattern <code>{text, url}</code>
513      * @return a map of text/href
514      */

515     private static Map JavaDoc applyPattern( String JavaDoc text )
516     {
517         if ( StringUtils.isEmpty( text ) )
518         {
519             return null;
520         }
521
522         // Map defined by key/value name/href
523
// If href == null, it means
524
Map JavaDoc segments = new LinkedHashMap JavaDoc();
525
526         // TODO Special case http://jira.codehaus.org/browse/MEV-40
527
if ( text.indexOf( "${" ) != -1 )
528         {
529             int lastComma = text.lastIndexOf( "," );
530             int lastSemi = text.lastIndexOf( "}" );
531             if ( lastComma != -1 && lastSemi != -1 )
532             {
533                 segments.put( text.substring( lastComma + 1, lastSemi ).trim(), null );
534             }
535             else
536             {
537                 segments.put( text, null );
538             }
539
540             return segments;
541         }
542
543         boolean inQuote = false;
544         int braceStack = 0;
545         int lastOffset = 0;
546
547         for ( int i = 0; i < text.length(); i++ )
548         {
549             char ch = text.charAt( i );
550
551             if ( ch == '\'' && !inQuote )
552             {
553                 // handle: ''
554
if ( i + 1 < text.length() && text.charAt( i + 1 ) == '\'' )
555                 {
556                     i++;
557                 }
558                 else
559                 {
560                     inQuote = true;
561                 }
562             }
563             else
564             {
565                 switch ( ch )
566                 {
567                     case '{':
568                         if ( !inQuote )
569                         {
570                             if ( braceStack == 0 )
571                             {
572                                 if ( i != 0 ) // handle { at first character
573
{
574                                     segments.put( text.substring( lastOffset, i ), null );
575                                 }
576                                 lastOffset = i + 1;
577                                 braceStack++;
578                             }
579                         }
580                         break;
581                     case '}':
582                         if ( !inQuote )
583                         {
584                             braceStack--;
585                             if ( braceStack == 0 )
586                             {
587                                 String JavaDoc subString = text.substring( lastOffset, i );
588                                 lastOffset = i + 1;
589
590                                 int lastComma = subString.lastIndexOf( "," );
591                                 if ( lastComma != -1 )
592                                 {
593                                     segments.put( subString.substring( 0, lastComma ).trim(),
594                                                   subString.substring( lastComma + 1 ).trim() );
595                                 }
596                                 else
597                                 {
598                                     segments.put( subString.substring( 0, lastComma ).trim(), null );
599                                 }
600                             }
601                         }
602                         break;
603                     case '\'':
604                         inQuote = false;
605                         break;
606                     default:
607                         break;
608                 }
609             }
610         }
611
612         if ( !StringUtils.isEmpty( text.substring( lastOffset, text.length() ) ) )
613         {
614             segments.put( text.substring( lastOffset, text.length() ), null );
615         }
616
617         if ( braceStack != 0 )
618         {
619             throw new IllegalArgumentException JavaDoc( "Unmatched braces in the pattern." );
620         }
621
622         return Collections.unmodifiableMap( segments );
623     }
624
625     public abstract String JavaDoc getTitle();
626
627     protected abstract void renderBody();
628 }
629
Popular Tags