1 package org.apache.maven.archetype.mojos;
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
12
13
14
15
16
17
18
19 @SuppressWarnings( "all" )
20 public class HelpMojo
21 extends AbstractMojo
22 {
23
24
25
26
27
28 private boolean detail;
29
30
31
32
33
34
35 private java.lang.String goal;
36
37
38
39
40
41
42 private int lineLength;
43
44
45
46
47
48
49 private int indentSize;
50
51
52
53 public void execute()
54 throws MojoExecutionException
55 {
56 if ( lineLength <= 0 )
57 {
58 getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
59 lineLength = 80;
60 }
61 if ( indentSize <= 0 )
62 {
63 getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
64 indentSize = 2;
65 }
66
67 StringBuffer sb = new StringBuffer();
68
69 append( sb, "org.apache.maven.plugins:maven-archetype-plugin:2.2", 0 );
70 append( sb, "", 0 );
71
72 append( sb, "Maven Archetype Plugin", 0 );
73 append( sb, "Maven Archetype is a set of tools to deal with archetypes, i.e. an abstract representation of a kind of project that can be instantiated into a concrete customized Maven project. An archetype knows which files will be part of the instantiated project and which properties to fill to properly customize the project.", 1 );
74 append( sb, "", 0 );
75
76 if ( goal == null || goal.length() <= 0 )
77 {
78 append( sb, "This plugin has 8 goals:", 0 );
79 append( sb, "", 0 );
80 }
81
82 if ( goal == null || goal.length() <= 0 || "crawl".equals( goal ) )
83 {
84 append( sb, "archetype:crawl", 0 );
85 append( sb, "Crawl a Maven repository (filesystem, not HTTP) and creates a catalog file.", 1 );
86 append( sb, "", 0 );
87 if ( detail )
88 {
89 append( sb, "Available parameters:", 1 );
90 append( sb, "", 0 );
91
92 append( sb, "catalogFile", 2 );
93 append( sb, "The archetype\'s catalog to update.", 3 );
94 append( sb, "Expression: ${catalog}", 3 );
95 append( sb, "", 0 );
96
97 append( sb, "repository (Default: ${settings.localRepository})", 2 );
98 append( sb, "The repository to crawl.", 3 );
99 append( sb, "Expression: ${repository}", 3 );
100 append( sb, "", 0 );
101 }
102 }
103
104 if ( goal == null || goal.length() <= 0 || "create".equals( goal ) )
105 {
106 append( sb, "archetype:create", 0 );
107 append( sb, "Deprecated. Please use the generate mojo instead.", 1 );
108 if ( detail )
109 {
110 append( sb, "", 0 );
111 append( sb, "The archetype creation goal looks for an archetype with a given groupId, artifactId, and version and retrieves it from the remote repository. Once the archetype is retrieved, it is then processed against a set of user parameters to create a working Maven project.", 1 );
112 }
113 append( sb, "", 0 );
114 if ( detail )
115 {
116 append( sb, "Available parameters:", 1 );
117 append( sb, "", 0 );
118
119 append( sb, "archetypeArtifactId (Default: maven-archetype-quickstart)", 2 );
120 append( sb, "The Archetype Artifact Id to be used.", 3 );
121 append( sb, "Required: Yes", 3 );
122 append( sb, "Expression: ${archetypeArtifactId}", 3 );
123 append( sb, "", 0 );
124
125 append( sb, "archetypeGroupId (Default: org.apache.maven.archetypes)", 2 );
126 append( sb, "The Archetype Group Id to be used.", 3 );
127 append( sb, "Required: Yes", 3 );
128 append( sb, "Expression: ${archetypeGroupId}", 3 );
129 append( sb, "", 0 );
130
131 append( sb, "archetypeVersion (Default: RELEASE)", 2 );
132 append( sb, "The Archetype Version to be used.", 3 );
133 append( sb, "Required: Yes", 3 );
134 append( sb, "Expression: ${archetypeVersion}", 3 );
135 append( sb, "", 0 );
136
137 append( sb, "artifactId", 2 );
138 append( sb, "The Artifact Id of the project to be build.", 3 );
139 append( sb, "Expression: ${artifactId}", 3 );
140 append( sb, "", 0 );
141
142 append( sb, "basedir (Default: ${user.dir})", 2 );
143 append( sb, "(no description available)", 3 );
144 append( sb, "Expression: ${basedir}", 3 );
145 append( sb, "", 0 );
146
147 append( sb, "groupId", 2 );
148 append( sb, "The Group Id of the project to be build.", 3 );
149 append( sb, "Expression: ${groupId}", 3 );
150 append( sb, "", 0 );
151
152 append( sb, "localRepository", 2 );
153 append( sb, "Maven\'s local repository.", 3 );
154 append( sb, "Required: Yes", 3 );
155 append( sb, "Expression: ${localRepository}", 3 );
156 append( sb, "", 0 );
157
158 append( sb, "packageName", 2 );
159 append( sb, "The Package Name of the project to be build.", 3 );
160 append( sb, "Expression: ${packageName}", 3 );
161 append( sb, "", 0 );
162
163 append( sb, "pomRemoteRepositories", 2 );
164 append( sb, "The remote repositories available for discovering dependencies and extensions as indicated by the POM.", 3 );
165 append( sb, "Required: Yes", 3 );
166 append( sb, "Expression: ${project.remoteArtifactRepositories}", 3 );
167 append( sb, "", 0 );
168
169 append( sb, "project", 2 );
170 append( sb, "The project to be created an archetype of.", 3 );
171 append( sb, "Expression: ${project}", 3 );
172 append( sb, "", 0 );
173
174 append( sb, "remoteRepositories", 2 );
175 append( sb, "Other remote repositories available for discovering dependencies and extensions.", 3 );
176 append( sb, "Expression: ${remoteRepositories}", 3 );
177 append( sb, "", 0 );
178
179 append( sb, "version (Default: 1.0-SNAPSHOT)", 2 );
180 append( sb, "The Version of the project to be build.", 3 );
181 append( sb, "Required: Yes", 3 );
182 append( sb, "Expression: ${version}", 3 );
183 append( sb, "", 0 );
184 }
185 }
186
187 if ( goal == null || goal.length() <= 0 || "create-from-project".equals( goal ) )
188 {
189 append( sb, "archetype:create-from-project", 0 );
190 append( sb, "Creates an archetype project from the current project.\n\nThis goal reads your source and resource files, the values of its parameters, and properties you specify in a .property file, and uses them to create a Maven archetype project using the maven-archetype packaging. If you build the resulting project, it will create the archetype. You can then use this archetype to create new projects that resemble the original.\n\nThe maven-archetype-plugin uses Velocity to expand template files, and this documentation talks about \'Velocity Properties\', which are values substituted into Velocity templates. See The Velocity User\'s Guide for more information.\n\nThis goal modifies the text of the files of the current project to form the Velocity template files that make up the archetype.\n\nGAV\n\tThe GAV values for the current project are replaced by properties: groupId, artifactId, and version. The user chooses new values for these when generating a project from the archetype.\npackage\n\tAll the files under one specified Java (or cognate) package are relocated to a project that the user chooses when generating a project. References to the class name are replaced by a property reference. For example, if the current project\'s sources are in the package org.apache.saltedpeanuts, then any example of the string org.apache.saltedpeanuts is replaced with the Velocity property reference ${packageName}. When the user generates a project, this is in turn replaced by his or her choice of a package.\ncustom properties\n\tYou may identify additional strings that should be replaced by parameters. To add custom properties, you must use the propertyFile parameter to specify a property file. See the documentation for propertyFile for the details.\n\nNote that you may need to edit the results of this goal. This goal has no way to exclude unwanted files, or add copyright notices to the Velocity templates, or add more complex elements to the archetype metadata file.\n\nThis goal also generates a simple integration-test that exercises the generated archetype.\n", 1 );
191 append( sb, "", 0 );
192 if ( detail )
193 {
194 append( sb, "Available parameters:", 1 );
195 append( sb, "", 0 );
196
197 append( sb, "archetypeFilteredExtentions", 2 );
198 append( sb, "File extensions which are checked for project\'s text files (vs binary files).", 3 );
199 append( sb, "Expression: ${archetype.filteredExtentions}", 3 );
200 append( sb, "", 0 );
201
202 append( sb, "archetypeLanguages", 2 );
203 append( sb, "Directory names which are checked for project\'s sources main package.", 3 );
204 append( sb, "Expression: ${archetype.languages}", 3 );
205 append( sb, "", 0 );
206
207 append( sb, "archetypePostPhase (Default: package)", 2 );
208 append( sb, "The property telling which phase to call on the generated archetype. Interesting values are: package, integration-test, install and deploy.", 3 );
209 append( sb, "Expression: ${archetype.postPhase}", 3 );
210 append( sb, "", 0 );
211
212 append( sb, "archetypeRegistryFile", 2 );
213 append( sb, "The location of the registry file.", 3 );
214 append( sb, "Expression: ${user.home}/.m2/archetype.xml", 3 );
215 append( sb, "", 0 );
216
217 append( sb, "defaultEncoding (Default: UTF-8)", 2 );
218 append( sb, "Velocity templates encoding.", 3 );
219 append( sb, "Expression: ${archetype.encoding}", 3 );
220 append( sb, "", 0 );
221
222 append( sb, "interactive (Default: false)", 2 );
223 append( sb, "Enable the interactive mode to define the archetype from the project.", 3 );
224 append( sb, "Expression: ${interactive}", 3 );
225 append( sb, "", 0 );
226
227 append( sb, "keepParent", 2 );
228 append( sb, "POMs in archetype are created with their initial parent. This property is ignored when preserveCData is true.", 3 );
229 append( sb, "Expression: ${archetype.keepParent}", 3 );
230 append( sb, "", 0 );
231
232 append( sb, "outputDirectory", 2 );
233 append( sb, "The directory where the archetype should be created.", 3 );
234 append( sb, "Expression: ${project.build.directory}/generated-sources/archetype", 3 );
235 append( sb, "", 0 );
236
237 append( sb, "packageName", 2 );
238 append( sb, "The package name for Java source files to be incorporated in the archetype and and relocated to the package that the user selects.", 3 );
239 append( sb, "Expression: ${packageName}", 3 );
240 append( sb, "", 0 );
241
242 append( sb, "partialArchetype", 2 );
243 append( sb, "Create a partial archetype.", 3 );
244 append( sb, "Expression: ${archetype.partialArchetype}", 3 );
245 append( sb, "", 0 );
246
247 append( sb, "preserveCData", 2 );
248 append( sb, "Create pom\'s velocity templates with CDATA preservation. This uses the String.replaceAll() method and risks to have some overly replacement capabilities (beware of \'1.0\' value).", 3 );
249 append( sb, "Expression: ${archetype.preserveCData}", 3 );
250 append( sb, "", 0 );
251
252 append( sb, "propertyFile", 2 );
253 append( sb, "The property file that holds the plugin configuration. If this is provided, then the plugin reads properties from here. The properties in here can be standard properties listed below or custom properties for this archetype. The standard properties are below. Several of them overlap parameters of this goal; it\'s better to just set the parameter.\npackage\n\tSee the packageName parameter.\narchetype.languages\n\tSee the archetypeLanguages parameter.\ngroupId\n\tThe default groupId of the generated project.\nartifactId\n\tThe default artifactId of the generated project.\nversion\n\tThe default version of the generated project.\narchetype.filteredExtensions\n\tSee the filteredExensions parameter.\nCustom Properties\nCustom properties allow you to replace some constant values in the project\'s files with Velocity macro references. When a user generates a project from your archetype he or she gets the opportunity to replace the value from the source project.\n\nCustom property names may not contain the \'.\' character.\n\nFor example, if you include a line like the following in your property file:\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0cxf-version=2.5.1-SNAPSHOT\nthe plugin will search your files for the string\n2.5.1-SNAPSHOT\nand replace them with references to a velocity macro\ncxf-version\n. It will then list\ncxf-version\nas a\nrequiredProperty\nin the archetype-metadata.xml, with\n2.5.1-SNAPSHOT\nas the default value.\n\n", 3 );
254 append( sb, "Expression: ${archetype.properties}", 3 );
255 append( sb, "", 0 );
256
257 append( sb, "testMode", 2 );
258 append( sb, "(no description available)", 3 );
259 append( sb, "Expression: ${testMode}", 3 );
260 append( sb, "", 0 );
261 }
262 }
263
264 if ( goal == null || goal.length() <= 0 || "generate".equals( goal ) )
265 {
266 append( sb, "archetype:generate", 0 );
267 append( sb, "Generates a new project from an archetype, or updated the actual project if using a partial archetype. If the project is fully generated, it is generated in a directory corresponding to its artifactId. If the project is updated with a partial archetype, it is done in the current directory.", 1 );
268 append( sb, "", 0 );
269 if ( detail )
270 {
271 append( sb, "Available parameters:", 1 );
272 append( sb, "", 0 );
273
274 append( sb, "archetypeArtifactId", 2 );
275 append( sb, "The archetype\'s artifactId.", 3 );
276 append( sb, "Expression: ${archetypeArtifactId}", 3 );
277 append( sb, "", 0 );
278
279 append( sb, "archetypeCatalog (Default: remote,local)", 2 );
280 append( sb, "The archetype catalogs to use to build a list and let the user choose from. It is a comma separated list of catalogs. Catalogs use following schemes:\n-\t\'file://...\' with archetype-catalog.xml automatically appended when pointing to a directory\n-\t\'http://...\' or \'https://...\' with archetype-catalog.xml always appended\n-\t\'local\' which is the shortcut for \'file://~/.m2/archetype-catalog.xml\'\n-\t\'remote\' which is the shortcut for Maven Central repository, ie \'http://repo1.maven.org/maven2\'\n-\t\'internal\' which is an internal catalog\nSince 2.0-alpha-5, default value is no longer internal,local but remote,local. If Maven Central repository catalog file is empty, internal catalog is used instead.", 3 );
281 append( sb, "Expression: ${archetypeCatalog}", 3 );
282 append( sb, "", 0 );
283
284 append( sb, "archetypeGroupId", 2 );
285 append( sb, "The archetype\'s groupId.", 3 );
286 append( sb, "Expression: ${archetypeGroupId}", 3 );
287 append( sb, "", 0 );
288
289 append( sb, "archetypeRepository", 2 );
290 append( sb, "The archetype\'s repository.", 3 );
291 append( sb, "Expression: ${archetypeRepository}", 3 );
292 append( sb, "", 0 );
293
294 append( sb, "archetypeVersion", 2 );
295 append( sb, "The archetype\'s version.", 3 );
296 append( sb, "Expression: ${archetypeVersion}", 3 );
297 append( sb, "", 0 );
298
299 append( sb, "basedir", 2 );
300 append( sb, "(no description available)", 3 );
301 append( sb, "Expression: ${basedir}", 3 );
302 append( sb, "", 0 );
303
304 append( sb, "filter", 2 );
305 append( sb, "Applying some filter on displayed archetypes list: format is artifactId or groupId:artifactId.\n-\torg.apache: -> displays all archetypes which contain org.apache in groupId\n-\t:jee or jee -> displays all archetypes which contain jee in artifactId\n-\torg.apache:jee -> displays all archetypes which contain org.apache in groupId AND jee in artifactId\n", 3 );
306 append( sb, "Expression: ${filter}", 3 );
307 append( sb, "", 0 );
308
309 append( sb, "goals", 2 );
310 append( sb, "Additional goals to immediately run on the project created from the archetype.", 3 );
311 append( sb, "Expression: ${goals}", 3 );
312 append( sb, "", 0 );
313
314 append( sb, "interactiveMode (Default: ${settings.interactiveMode})", 2 );
315 append( sb, "User settings use to check the interactiveMode.", 3 );
316 append( sb, "Required: Yes", 3 );
317 append( sb, "Expression: ${interactiveMode}", 3 );
318 append( sb, "", 0 );
319 }
320 }
321
322 if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
323 {
324 append( sb, "archetype:help", 0 );
325 append( sb, "Display help information on maven-archetype-plugin.\nCall\n\u00a0\u00a0mvn\u00a0archetype:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
326 append( sb, "", 0 );
327 if ( detail )
328 {
329 append( sb, "Available parameters:", 1 );
330 append( sb, "", 0 );
331
332 append( sb, "detail (Default: false)", 2 );
333 append( sb, "If true, display all settable properties for each goal.", 3 );
334 append( sb, "Expression: ${detail}", 3 );
335 append( sb, "", 0 );
336
337 append( sb, "goal", 2 );
338 append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
339 append( sb, "Expression: ${goal}", 3 );
340 append( sb, "", 0 );
341
342 append( sb, "indentSize (Default: 2)", 2 );
343 append( sb, "The number of spaces per indentation level, should be positive.", 3 );
344 append( sb, "Expression: ${indentSize}", 3 );
345 append( sb, "", 0 );
346
347 append( sb, "lineLength (Default: 80)", 2 );
348 append( sb, "The maximum length of a display line, should be positive.", 3 );
349 append( sb, "Expression: ${lineLength}", 3 );
350 append( sb, "", 0 );
351 }
352 }
353
354 if ( goal == null || goal.length() <= 0 || "integration-test".equals( goal ) )
355 {
356 append( sb, "archetype:integration-test", 0 );
357 append( sb, "Execute the archetype integration tests, consisting in generating projects from the current archetype and optionally comparing generated projects with reference copy.\n\nEach IT consists of a sub-directory in src/test/resources/projects containing:\n\n-\ta goal.txt file, containing a list of goals to run against the generated project (can be empty, content ignored before maven-archetype-plugin 2.1),\n-\tan archetype.properties file, containing properties for project generation,\n-\tan optional reference/ directory containing a reference copy of the expected project created from the IT.\nNotice that it is expected to be run as part as of a build after the package phase and not directly as a goal from CLI.", 1 );
358 append( sb, "", 0 );
359 if ( detail )
360 {
361 append( sb, "Available parameters:", 1 );
362 append( sb, "", 0 );
363
364 append( sb, "debug (Default: false)", 2 );
365 append( sb, "Whether to show debug statements in the build output.", 3 );
366 append( sb, "Expression: ${archetype.test.debug}", 3 );
367 append( sb, "", 0 );
368
369 append( sb, "encoding (Default: ${project.build.sourceEncoding})", 2 );
370 append( sb, "The file encoding for the post-build script.", 3 );
371 append( sb, "Expression: ${encoding}", 3 );
372 append( sb, "", 0 );
373
374 append( sb, "filterProperties", 2 );
375 append( sb, "A list of additional properties which will be used to filter tokens in settings.xml", 3 );
376 append( sb, "", 0 );
377
378 append( sb, "noLog (Default: false)", 2 );
379 append( sb, "Suppress logging to the build.log file.", 3 );
380 append( sb, "Expression: ${archetype.test.noLog}", 3 );
381 append( sb, "", 0 );
382
383 append( sb, "postBuildHookScript (Default: verify)", 2 );
384 append( sb, "Relative path of a cleanup/verification hook script to run after executing the build. This script may be written with either BeanShell or Groovy. If the file extension is omitted (e.g. verify), the plugin searches for the file by trying out the well-known extensions .bsh and .groovy. If this script exists for a particular project but returns any non-null value different from true or throws an exception, the corresponding build is flagged as a failure.", 3 );
385 append( sb, "Expression: ${archetype.test.verifyScript}", 3 );
386 append( sb, "", 0 );
387
388 append( sb, "settingsFile", 2 );
389 append( sb, "Path to an alternate settings.xml to use for Maven invocation with all ITs. Note that the <localRepository> element of this settings file is always ignored, i.e. the path given by the parameter localRepositoryPath is dominant.", 3 );
390 append( sb, "Expression: ${archetype.test.settingsFile}", 3 );
391 append( sb, "", 0 );
392
393 append( sb, "showVersion (Default: false)", 2 );
394 append( sb, "flag to enable show mvn version used for running its (cli option : -V,--show-version )", 3 );
395 append( sb, "Expression: ${archetype.test.showVersion}", 3 );
396 append( sb, "", 0 );
397
398 append( sb, "streamLogs (Default: true)", 2 );
399 append( sb, "Flag used to determine whether the build logs should be output to the normal mojo log.", 3 );
400 append( sb, "Expression: ${archetype.test.streamLogs}", 3 );
401 append( sb, "", 0 );
402
403 append( sb, "testProjectsDirectory (Default: ${project.build.testOutputDirectory}/projects)", 2 );
404 append( sb, "Directory of test projects", 3 );
405 append( sb, "Required: Yes", 3 );
406 append( sb, "Expression: ${archetype.test.projectsDirectory}", 3 );
407 append( sb, "", 0 );
408 }
409 }
410
411 if ( goal == null || goal.length() <= 0 || "jar".equals( goal ) )
412 {
413 append( sb, "archetype:jar", 0 );
414 append( sb, "Build a JAR from the current Archetype project.", 1 );
415 append( sb, "", 0 );
416 if ( detail )
417 {
418 append( sb, "Available parameters:", 1 );
419 append( sb, "", 0 );
420
421 append( sb, "archetypeDirectory", 2 );
422 append( sb, "Directory containing the classes.", 3 );
423 append( sb, "Required: Yes", 3 );
424 append( sb, "Expression: ${project.build.outputDirectory}", 3 );
425 append( sb, "", 0 );
426
427 append( sb, "finalName", 2 );
428 append( sb, "Name of the generated JAR.", 3 );
429 append( sb, "Required: Yes", 3 );
430 append( sb, "Expression: ${project.build.finalName}", 3 );
431 append( sb, "", 0 );
432
433 append( sb, "outputDirectory", 2 );
434 append( sb, "Directory containing the generated JAR.", 3 );
435 append( sb, "Required: Yes", 3 );
436 append( sb, "Expression: ${project.build.directory}", 3 );
437 append( sb, "", 0 );
438 }
439 }
440
441 if ( goal == null || goal.length() <= 0 || "update-local-catalog".equals( goal ) )
442 {
443 append( sb, "archetype:update-local-catalog", 0 );
444 append( sb, "Updates the local catalog", 1 );
445 append( sb, "", 0 );
446 if ( detail )
447 {
448 append( sb, "Available parameters:", 1 );
449 append( sb, "", 0 );
450 }
451 }
452
453 if ( getLog().isInfoEnabled() )
454 {
455 getLog().info( sb.toString() );
456 }
457 }
458
459
460
461
462
463
464
465
466
467
468 private static String repeat( String str, int repeat )
469 {
470 StringBuffer buffer = new StringBuffer( repeat * str.length() );
471
472 for ( int i = 0; i < repeat; i++ )
473 {
474 buffer.append( str );
475 }
476
477 return buffer.toString();
478 }
479
480
481
482
483
484
485
486
487
488 private void append( StringBuffer sb, String description, int indent )
489 {
490 for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
491 {
492 sb.append( it.next().toString() ).append( '\n' );
493 }
494 }
495
496
497
498
499
500
501
502
503
504
505
506 private static List toLines( String text, int indent, int indentSize, int lineLength )
507 {
508 List<String> lines = new ArrayList<String>();
509
510 String ind = repeat( "\t", indent );
511 String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
512 for ( int i = 0; i < plainLines.length; i++ )
513 {
514 toLines( lines, ind + plainLines[i], indentSize, lineLength );
515 }
516
517 return lines;
518 }
519
520
521
522
523
524
525
526
527
528 private static void toLines( List<String> lines, String line, int indentSize, int lineLength )
529 {
530 int lineIndent = getIndentLevel( line );
531 StringBuffer buf = new StringBuffer( 256 );
532 String[] tokens = line.split( " +" );
533 for ( int i = 0; i < tokens.length; i++ )
534 {
535 String token = tokens[i];
536 if ( i > 0 )
537 {
538 if ( buf.length() + token.length() >= lineLength )
539 {
540 lines.add( buf.toString() );
541 buf.setLength( 0 );
542 buf.append( repeat( " ", lineIndent * indentSize ) );
543 }
544 else
545 {
546 buf.append( ' ' );
547 }
548 }
549 for ( int j = 0; j < token.length(); j++ )
550 {
551 char c = token.charAt( j );
552 if ( c == '\t' )
553 {
554 buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
555 }
556 else if ( c == '\u00A0' )
557 {
558 buf.append( ' ' );
559 }
560 else
561 {
562 buf.append( c );
563 }
564 }
565 }
566 lines.add( buf.toString() );
567 }
568
569
570
571
572
573
574
575 private static int getIndentLevel( String line )
576 {
577 int level = 0;
578 for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
579 {
580 level++;
581 }
582 for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
583 {
584 if ( line.charAt( i ) == '\t' )
585 {
586 level++;
587 break;
588 }
589 }
590 return level;
591 }
592 }