View Javadoc

1   package org.apache.maven.plugin.jxr;
2   
3   import java.util.ArrayList;
4   import java.util.Iterator;
5   import java.util.List;
6   
7   import org.apache.maven.plugin.AbstractMojo;
8   import org.apache.maven.plugin.MojoExecutionException;
9   
10  /**
11   * Display help information on maven-jxr-plugin.<br/> Call <pre>  mvn jxr:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
12   *
13   * @version generated on Tue Jul 19 12:45:23 EDT 2011
14   * @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.8)
15   * @goal help
16   * @requiresProject false
17   * @threadSafe
18   */
19  public class HelpMojo
20      extends AbstractMojo
21  {
22      /**
23       * If <code>true</code>, display all settable properties for each goal.
24       * 
25       * @parameter expression="${detail}" default-value="false"
26       */
27      private boolean detail;
28  
29      /**
30       * The name of the goal for which to show help. If unspecified, all goals will be displayed.
31       * 
32       * @parameter expression="${goal}"
33       */
34      private java.lang.String goal;
35  
36      /**
37       * The maximum length of a display line, should be positive.
38       * 
39       * @parameter expression="${lineLength}" default-value="80"
40       */
41      private int lineLength;
42  
43      /**
44       * The number of spaces per indentation level, should be positive.
45       * 
46       * @parameter expression="${indentSize}" default-value="2"
47       */
48      private int indentSize;
49  
50  
51      /** {@inheritDoc} */
52      public void execute()
53          throws MojoExecutionException
54      {
55          if ( lineLength <= 0 )
56          {
57              getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
58              lineLength = 80;
59          }
60          if ( indentSize <= 0 )
61          {
62              getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
63              indentSize = 2;
64          }
65  
66          StringBuffer sb = new StringBuffer();
67  
68          append( sb, "org.apache.maven.plugins:maven-jxr-plugin:2.3", 0 );
69          append( sb, "", 0 );
70  
71          append( sb, "Maven JXR Plugin", 0 );
72          append( sb, "Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project\'s build, reporting and documentation from a central piece of information.", 1 );
73          append( sb, "", 0 );
74  
75          if ( goal == null || goal.length() <= 0 )
76          {
77              append( sb, "This plugin has 5 goals:", 0 );
78              append( sb, "", 0 );
79          }
80  
81          if ( goal == null || goal.length() <= 0 || "aggregate".equals( goal ) )
82          {
83              append( sb, "jxr:aggregate", 0 );
84              append( sb, "Generates a combined JXR report in an aggregating project.", 1 );
85              append( sb, "", 0 );
86              if ( detail )
87              {
88                  append( sb, "Available parameters:", 1 );
89                  append( sb, "", 0 );
90  
91                  append( sb, "aggregate (Default: false)", 2 );
92                  append( sb, "Deprecated. since 2.3. Use the goals jxr:aggregate and jxr:test-aggregate instead.", 3 );
93                  append( sb, "", 0 );
94                  append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
95                  append( sb, "Expression: ${aggregate}", 3 );
96                  append( sb, "", 0 );
97  
98                  append( sb, "bottom (Default: Copyright &#169; {inceptionYear}-{currentYear} {projectOrganizationName}. All Rights Reserved.)", 2 );
99                  append( sb, "String uses at the bottom of the Xref HTML files.", 3 );
100                 append( sb, "Expression: ${bottom}", 3 );
101                 append( sb, "", 0 );
102 
103                 append( sb, "destDir", 2 );
104                 append( sb, "Folder where the Xref files will be copied to.", 3 );
105                 append( sb, "Expression: ${project.reporting.outputDirectory}/xref", 3 );
106                 append( sb, "", 0 );
107 
108                 append( sb, "docTitle", 2 );
109                 append( sb, "Title of main page of the Xref HTML files.", 3 );
110                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
111                 append( sb, "", 0 );
112 
113                 append( sb, "excludes", 2 );
114                 append( sb, "A list of exclude patterns to use. By default no files are excluded.", 3 );
115                 append( sb, "Expression: ${excludes}", 3 );
116                 append( sb, "", 0 );
117 
118                 append( sb, "includes", 2 );
119                 append( sb, "A list of include patterns to use. By default all .java files are included.", 3 );
120                 append( sb, "Expression: ${includes}", 3 );
121                 append( sb, "", 0 );
122 
123                 append( sb, "inputEncoding (Default: ${project.build.sourceEncoding})", 2 );
124                 append( sb, "File input encoding.", 3 );
125                 append( sb, "Expression: ${encoding}", 3 );
126                 append( sb, "", 0 );
127 
128                 append( sb, "javadocDir", 2 );
129                 append( sb, "Folder where Javadoc is generated for this project.", 3 );
130                 append( sb, "Expression: ${project.reporting.outputDirectory}/apidocs", 3 );
131                 append( sb, "", 0 );
132 
133                 append( sb, "linkJavadoc (Default: true)", 2 );
134                 append( sb, "Link the Javadoc from the Source XRef. Defaults to true and will link automatically if javadoc plugin is being used.", 3 );
135                 append( sb, "Expression: ${linkJavadoc}", 3 );
136                 append( sb, "", 0 );
137 
138                 append( sb, "outputDirectory", 2 );
139                 append( sb, "Output folder where the main page of the report will be generated. Note that this parameter is only relevant if the goal is run directly from the command line or from the default lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin will be used instead.", 3 );
140                 append( sb, "Required: Yes", 3 );
141                 append( sb, "Expression: ${project.reporting.outputDirectory}", 3 );
142                 append( sb, "", 0 );
143 
144                 append( sb, "outputEncoding (Default: ${project.reporting.outputEncoding})", 2 );
145                 append( sb, "File output encoding.", 3 );
146                 append( sb, "Expression: ${outputEncoding}", 3 );
147                 append( sb, "", 0 );
148 
149                 append( sb, "skip (Default: false)", 2 );
150                 append( sb, "Whether to skip this execution.", 3 );
151                 append( sb, "Expression: ${maven.jxr.skip}", 3 );
152                 append( sb, "", 0 );
153 
154                 append( sb, "sourcePath", 2 );
155                 append( sb, "Specifies the source path where the java files are located. The paths are separated by \';\'.", 3 );
156                 append( sb, "Expression: ${sourcePath}", 3 );
157                 append( sb, "", 0 );
158 
159                 append( sb, "stylesheet (Default: stylesheet.css)", 2 );
160                 append( sb, "Style sheet used for the Xref HTML files. Should not be used. If used, should be an absolute path, like \'${basedir}/myStyles.css\'.", 3 );
161                 append( sb, "", 0 );
162 
163                 append( sb, "templateDir (Default: templates)", 2 );
164                 append( sb, "Directory where Velocity templates can be found to generate overviews, frames and summaries. Should not be used. If used, should be an absolute path, like \'${basedir}/myTemplates\'.", 3 );
165                 append( sb, "", 0 );
166 
167                 append( sb, "windowTitle", 2 );
168                 append( sb, "Title of window of the Xref HTML files.", 3 );
169                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
170                 append( sb, "", 0 );
171             }
172         }
173 
174         if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
175         {
176             append( sb, "jxr:help", 0 );
177             append( sb, "Display help information on maven-jxr-plugin.\nCall\n\u00a0\u00a0mvn\u00a0jxr:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
178             append( sb, "", 0 );
179             if ( detail )
180             {
181                 append( sb, "Available parameters:", 1 );
182                 append( sb, "", 0 );
183 
184                 append( sb, "detail (Default: false)", 2 );
185                 append( sb, "If true, display all settable properties for each goal.", 3 );
186                 append( sb, "Expression: ${detail}", 3 );
187                 append( sb, "", 0 );
188 
189                 append( sb, "goal", 2 );
190                 append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
191                 append( sb, "Expression: ${goal}", 3 );
192                 append( sb, "", 0 );
193 
194                 append( sb, "indentSize (Default: 2)", 2 );
195                 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
196                 append( sb, "Expression: ${indentSize}", 3 );
197                 append( sb, "", 0 );
198 
199                 append( sb, "lineLength (Default: 80)", 2 );
200                 append( sb, "The maximum length of a display line, should be positive.", 3 );
201                 append( sb, "Expression: ${lineLength}", 3 );
202                 append( sb, "", 0 );
203             }
204         }
205 
206         if ( goal == null || goal.length() <= 0 || "jxr".equals( goal ) )
207         {
208             append( sb, "jxr:jxr", 0 );
209             append( sb, "Creates an html-based, cross referenced version of Java source code for a project.", 1 );
210             append( sb, "", 0 );
211             if ( detail )
212             {
213                 append( sb, "Available parameters:", 1 );
214                 append( sb, "", 0 );
215 
216                 append( sb, "aggregate (Default: false)", 2 );
217                 append( sb, "Deprecated. since 2.3. Use the goals jxr:aggregate and jxr:test-aggregate instead.", 3 );
218                 append( sb, "", 0 );
219                 append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
220                 append( sb, "Expression: ${aggregate}", 3 );
221                 append( sb, "", 0 );
222 
223                 append( sb, "bottom (Default: Copyright &#169; {inceptionYear}-{currentYear} {projectOrganizationName}. All Rights Reserved.)", 2 );
224                 append( sb, "String uses at the bottom of the Xref HTML files.", 3 );
225                 append( sb, "Expression: ${bottom}", 3 );
226                 append( sb, "", 0 );
227 
228                 append( sb, "destDir", 2 );
229                 append( sb, "Folder where the Xref files will be copied to.", 3 );
230                 append( sb, "Expression: ${project.reporting.outputDirectory}/xref", 3 );
231                 append( sb, "", 0 );
232 
233                 append( sb, "docTitle", 2 );
234                 append( sb, "Title of main page of the Xref HTML files.", 3 );
235                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
236                 append( sb, "", 0 );
237 
238                 append( sb, "excludes", 2 );
239                 append( sb, "A list of exclude patterns to use. By default no files are excluded.", 3 );
240                 append( sb, "Expression: ${excludes}", 3 );
241                 append( sb, "", 0 );
242 
243                 append( sb, "includes", 2 );
244                 append( sb, "A list of include patterns to use. By default all .java files are included.", 3 );
245                 append( sb, "Expression: ${includes}", 3 );
246                 append( sb, "", 0 );
247 
248                 append( sb, "inputEncoding (Default: ${project.build.sourceEncoding})", 2 );
249                 append( sb, "File input encoding.", 3 );
250                 append( sb, "Expression: ${encoding}", 3 );
251                 append( sb, "", 0 );
252 
253                 append( sb, "javadocDir", 2 );
254                 append( sb, "Folder where Javadoc is generated for this project.", 3 );
255                 append( sb, "Expression: ${project.reporting.outputDirectory}/apidocs", 3 );
256                 append( sb, "", 0 );
257 
258                 append( sb, "linkJavadoc (Default: true)", 2 );
259                 append( sb, "Link the Javadoc from the Source XRef. Defaults to true and will link automatically if javadoc plugin is being used.", 3 );
260                 append( sb, "Expression: ${linkJavadoc}", 3 );
261                 append( sb, "", 0 );
262 
263                 append( sb, "outputDirectory", 2 );
264                 append( sb, "Output folder where the main page of the report will be generated. Note that this parameter is only relevant if the goal is run directly from the command line or from the default lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin will be used instead.", 3 );
265                 append( sb, "Required: Yes", 3 );
266                 append( sb, "Expression: ${project.reporting.outputDirectory}", 3 );
267                 append( sb, "", 0 );
268 
269                 append( sb, "outputEncoding (Default: ${project.reporting.outputEncoding})", 2 );
270                 append( sb, "File output encoding.", 3 );
271                 append( sb, "Expression: ${outputEncoding}", 3 );
272                 append( sb, "", 0 );
273 
274                 append( sb, "skip (Default: false)", 2 );
275                 append( sb, "Whether to skip this execution.", 3 );
276                 append( sb, "Expression: ${maven.jxr.skip}", 3 );
277                 append( sb, "", 0 );
278 
279                 append( sb, "sourcePath", 2 );
280                 append( sb, "Specifies the source path where the java files are located. The paths are separated by \';\'.", 3 );
281                 append( sb, "Expression: ${sourcePath}", 3 );
282                 append( sb, "", 0 );
283 
284                 append( sb, "stylesheet (Default: stylesheet.css)", 2 );
285                 append( sb, "Style sheet used for the Xref HTML files. Should not be used. If used, should be an absolute path, like \'${basedir}/myStyles.css\'.", 3 );
286                 append( sb, "", 0 );
287 
288                 append( sb, "templateDir (Default: templates)", 2 );
289                 append( sb, "Directory where Velocity templates can be found to generate overviews, frames and summaries. Should not be used. If used, should be an absolute path, like \'${basedir}/myTemplates\'.", 3 );
290                 append( sb, "", 0 );
291 
292                 append( sb, "windowTitle", 2 );
293                 append( sb, "Title of window of the Xref HTML files.", 3 );
294                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
295                 append( sb, "", 0 );
296             }
297         }
298 
299         if ( goal == null || goal.length() <= 0 || "test-aggregate".equals( goal ) )
300         {
301             append( sb, "jxr:test-aggregate", 0 );
302             append( sb, "Generates a combined JXR report for test code in an aggregating project.", 1 );
303             append( sb, "", 0 );
304             if ( detail )
305             {
306                 append( sb, "Available parameters:", 1 );
307                 append( sb, "", 0 );
308 
309                 append( sb, "aggregate (Default: false)", 2 );
310                 append( sb, "Deprecated. since 2.3. Use the goals jxr:aggregate and jxr:test-aggregate instead.", 3 );
311                 append( sb, "", 0 );
312                 append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
313                 append( sb, "Expression: ${aggregate}", 3 );
314                 append( sb, "", 0 );
315 
316                 append( sb, "bottom (Default: Copyright &#169; {inceptionYear}-{currentYear} {projectOrganizationName}. All Rights Reserved.)", 2 );
317                 append( sb, "String uses at the bottom of the Xref HTML files.", 3 );
318                 append( sb, "Expression: ${bottom}", 3 );
319                 append( sb, "", 0 );
320 
321                 append( sb, "destDir", 2 );
322                 append( sb, "Folder where the Xref files will be copied to.", 3 );
323                 append( sb, "Expression: ${project.reporting.outputDirectory}/xref-test", 3 );
324                 append( sb, "", 0 );
325 
326                 append( sb, "docTitle", 2 );
327                 append( sb, "Title of main page of the Xref HTML files.", 3 );
328                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
329                 append( sb, "", 0 );
330 
331                 append( sb, "excludes", 2 );
332                 append( sb, "A list of exclude patterns to use. By default no files are excluded.", 3 );
333                 append( sb, "Expression: ${excludes}", 3 );
334                 append( sb, "", 0 );
335 
336                 append( sb, "includes", 2 );
337                 append( sb, "A list of include patterns to use. By default all .java files are included.", 3 );
338                 append( sb, "Expression: ${includes}", 3 );
339                 append( sb, "", 0 );
340 
341                 append( sb, "inputEncoding (Default: ${project.build.sourceEncoding})", 2 );
342                 append( sb, "File input encoding.", 3 );
343                 append( sb, "Expression: ${encoding}", 3 );
344                 append( sb, "", 0 );
345 
346                 append( sb, "linkJavadoc (Default: true)", 2 );
347                 append( sb, "Link the Javadoc from the Source XRef. Defaults to true and will link automatically if javadoc plugin is being used.", 3 );
348                 append( sb, "Expression: ${linkJavadoc}", 3 );
349                 append( sb, "", 0 );
350 
351                 append( sb, "outputDirectory", 2 );
352                 append( sb, "Output folder where the main page of the report will be generated. Note that this parameter is only relevant if the goal is run directly from the command line or from the default lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin will be used instead.", 3 );
353                 append( sb, "Required: Yes", 3 );
354                 append( sb, "Expression: ${project.reporting.outputDirectory}", 3 );
355                 append( sb, "", 0 );
356 
357                 append( sb, "outputEncoding (Default: ${project.reporting.outputEncoding})", 2 );
358                 append( sb, "File output encoding.", 3 );
359                 append( sb, "Expression: ${outputEncoding}", 3 );
360                 append( sb, "", 0 );
361 
362                 append( sb, "skip (Default: false)", 2 );
363                 append( sb, "Whether to skip this execution.", 3 );
364                 append( sb, "Expression: ${maven.jxr.skip}", 3 );
365                 append( sb, "", 0 );
366 
367                 append( sb, "stylesheet (Default: stylesheet.css)", 2 );
368                 append( sb, "Style sheet used for the Xref HTML files. Should not be used. If used, should be an absolute path, like \'${basedir}/myStyles.css\'.", 3 );
369                 append( sb, "", 0 );
370 
371                 append( sb, "templateDir (Default: templates)", 2 );
372                 append( sb, "Directory where Velocity templates can be found to generate overviews, frames and summaries. Should not be used. If used, should be an absolute path, like \'${basedir}/myTemplates\'.", 3 );
373                 append( sb, "", 0 );
374 
375                 append( sb, "testJavadocDir", 2 );
376                 append( sb, "Folder where Test Javadoc is generated for this project.", 3 );
377                 append( sb, "Expression: ${project.reporting.outputDirectory}/testapidocs", 3 );
378                 append( sb, "", 0 );
379 
380                 append( sb, "windowTitle", 2 );
381                 append( sb, "Title of window of the Xref HTML files.", 3 );
382                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
383                 append( sb, "", 0 );
384             }
385         }
386 
387         if ( goal == null || goal.length() <= 0 || "test-jxr".equals( goal ) )
388         {
389             append( sb, "jxr:test-jxr", 0 );
390             append( sb, "Creates an html-based, cross referenced version of Java source code for a project\'s test sources.", 1 );
391             append( sb, "", 0 );
392             if ( detail )
393             {
394                 append( sb, "Available parameters:", 1 );
395                 append( sb, "", 0 );
396 
397                 append( sb, "aggregate (Default: false)", 2 );
398                 append( sb, "Deprecated. since 2.3. Use the goals jxr:aggregate and jxr:test-aggregate instead.", 3 );
399                 append( sb, "", 0 );
400                 append( sb, "Whether to build an aggregated report at the root, or build individual reports.", 3 );
401                 append( sb, "Expression: ${aggregate}", 3 );
402                 append( sb, "", 0 );
403 
404                 append( sb, "bottom (Default: Copyright &#169; {inceptionYear}-{currentYear} {projectOrganizationName}. All Rights Reserved.)", 2 );
405                 append( sb, "String uses at the bottom of the Xref HTML files.", 3 );
406                 append( sb, "Expression: ${bottom}", 3 );
407                 append( sb, "", 0 );
408 
409                 append( sb, "destDir", 2 );
410                 append( sb, "Folder where the Xref files will be copied to.", 3 );
411                 append( sb, "Expression: ${project.reporting.outputDirectory}/xref-test", 3 );
412                 append( sb, "", 0 );
413 
414                 append( sb, "docTitle", 2 );
415                 append( sb, "Title of main page of the Xref HTML files.", 3 );
416                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
417                 append( sb, "", 0 );
418 
419                 append( sb, "excludes", 2 );
420                 append( sb, "A list of exclude patterns to use. By default no files are excluded.", 3 );
421                 append( sb, "Expression: ${excludes}", 3 );
422                 append( sb, "", 0 );
423 
424                 append( sb, "includes", 2 );
425                 append( sb, "A list of include patterns to use. By default all .java files are included.", 3 );
426                 append( sb, "Expression: ${includes}", 3 );
427                 append( sb, "", 0 );
428 
429                 append( sb, "inputEncoding (Default: ${project.build.sourceEncoding})", 2 );
430                 append( sb, "File input encoding.", 3 );
431                 append( sb, "Expression: ${encoding}", 3 );
432                 append( sb, "", 0 );
433 
434                 append( sb, "linkJavadoc (Default: true)", 2 );
435                 append( sb, "Link the Javadoc from the Source XRef. Defaults to true and will link automatically if javadoc plugin is being used.", 3 );
436                 append( sb, "Expression: ${linkJavadoc}", 3 );
437                 append( sb, "", 0 );
438 
439                 append( sb, "outputDirectory", 2 );
440                 append( sb, "Output folder where the main page of the report will be generated. Note that this parameter is only relevant if the goal is run directly from the command line or from the default lifecycle. If the goal is run indirectly as part of a site generation, the output directory configured in the Maven Site Plugin will be used instead.", 3 );
441                 append( sb, "Required: Yes", 3 );
442                 append( sb, "Expression: ${project.reporting.outputDirectory}", 3 );
443                 append( sb, "", 0 );
444 
445                 append( sb, "outputEncoding (Default: ${project.reporting.outputEncoding})", 2 );
446                 append( sb, "File output encoding.", 3 );
447                 append( sb, "Expression: ${outputEncoding}", 3 );
448                 append( sb, "", 0 );
449 
450                 append( sb, "skip (Default: false)", 2 );
451                 append( sb, "Whether to skip this execution.", 3 );
452                 append( sb, "Expression: ${maven.jxr.skip}", 3 );
453                 append( sb, "", 0 );
454 
455                 append( sb, "stylesheet (Default: stylesheet.css)", 2 );
456                 append( sb, "Style sheet used for the Xref HTML files. Should not be used. If used, should be an absolute path, like \'${basedir}/myStyles.css\'.", 3 );
457                 append( sb, "", 0 );
458 
459                 append( sb, "templateDir (Default: templates)", 2 );
460                 append( sb, "Directory where Velocity templates can be found to generate overviews, frames and summaries. Should not be used. If used, should be an absolute path, like \'${basedir}/myTemplates\'.", 3 );
461                 append( sb, "", 0 );
462 
463                 append( sb, "testJavadocDir", 2 );
464                 append( sb, "Folder where Test Javadoc is generated for this project.", 3 );
465                 append( sb, "Expression: ${project.reporting.outputDirectory}/testapidocs", 3 );
466                 append( sb, "", 0 );
467 
468                 append( sb, "windowTitle", 2 );
469                 append( sb, "Title of window of the Xref HTML files.", 3 );
470                 append( sb, "Expression: ${project.name} ${project.version} Reference", 3 );
471                 append( sb, "", 0 );
472             }
473         }
474 
475         if ( getLog().isInfoEnabled() )
476         {
477             getLog().info( sb.toString() );
478         }
479     }
480 
481     /**
482      * <p>Repeat a String <code>n</code> times to form a new string.</p>
483      *
484      * @param str String to repeat
485      * @param repeat number of times to repeat str
486      * @return String with repeated String
487      * @throws NegativeArraySizeException if <code>repeat < 0</code>
488      * @throws NullPointerException if str is <code>null</code>
489      */
490     private static String repeat( String str, int repeat )
491     {
492         StringBuffer buffer = new StringBuffer( repeat * str.length() );
493 
494         for ( int i = 0; i < repeat; i++ )
495         {
496             buffer.append( str );
497         }
498 
499         return buffer.toString();
500     }
501 
502     /** 
503      * Append a description to the buffer by respecting the indentSize and lineLength parameters.
504      * <b>Note</b>: The last character is always a new line.
505      * 
506      * @param sb The buffer to append the description, not <code>null</code>.
507      * @param description The description, not <code>null</code>.
508      * @param indent The base indentation level of each line, must not be negative.
509      */
510     private void append( StringBuffer sb, String description, int indent )
511     {
512         for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
513         {
514             sb.append( it.next().toString() ).append( '\n' );
515         }
516     }
517 
518     /** 
519      * Splits the specified text into lines of convenient display length.
520      * 
521      * @param text The text to split into lines, must not be <code>null</code>.
522      * @param indent The base indentation level of each line, must not be negative.
523      * @param indentSize The size of each indentation, must not be negative.
524      * @param lineLength The length of the line, must not be negative.
525      * @return The sequence of display lines, never <code>null</code>.
526      * @throws NegativeArraySizeException if <code>indent < 0</code>
527      */
528     private static List toLines( String text, int indent, int indentSize, int lineLength )
529     {
530         List lines = new ArrayList();
531 
532         String ind = repeat( "\t", indent );
533         String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
534         for ( int i = 0; i < plainLines.length; i++ )
535         {
536             toLines( lines, ind + plainLines[i], indentSize, lineLength );
537         }
538 
539         return lines;
540     }
541 
542     /** 
543      * Adds the specified line to the output sequence, performing line wrapping if necessary.
544      * 
545      * @param lines The sequence of display lines, must not be <code>null</code>.
546      * @param line The line to add, must not be <code>null</code>.
547      * @param indentSize The size of each indentation, must not be negative.
548      * @param lineLength The length of the line, must not be negative.
549      */
550     private static void toLines( List lines, String line, int indentSize, int lineLength )
551     {
552         int lineIndent = getIndentLevel( line );
553         StringBuffer buf = new StringBuffer( 256 );
554         String[] tokens = line.split( " +" );
555         for ( int i = 0; i < tokens.length; i++ )
556         {
557             String token = tokens[i];
558             if ( i > 0 )
559             {
560                 if ( buf.length() + token.length() >= lineLength )
561                 {
562                     lines.add( buf.toString() );
563                     buf.setLength( 0 );
564                     buf.append( repeat( " ", lineIndent * indentSize ) );
565                 }
566                 else
567                 {
568                     buf.append( ' ' );
569                 }
570             }
571             for ( int j = 0; j < token.length(); j++ )
572             {
573                 char c = token.charAt( j );
574                 if ( c == '\t' )
575                 {
576                     buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
577                 }
578                 else if ( c == '\u00A0' )
579                 {
580                     buf.append( ' ' );
581                 }
582                 else
583                 {
584                     buf.append( c );
585                 }
586             }
587         }
588         lines.add( buf.toString() );
589     }
590 
591     /** 
592      * Gets the indentation level of the specified line.
593      * 
594      * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
595      * @return The indentation level of the line.
596      */
597     private static int getIndentLevel( String line )
598     {
599         int level = 0;
600         for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
601         {
602             level++;
603         }
604         for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
605         {
606             if ( line.charAt( i ) == '\t' )
607             {
608                 level++;
609                 break;
610             }
611         }
612         return level;
613     }
614 }