001package org.andromda.maven.plugin.andromdapp;
002
003import java.util.ArrayList;
004import java.util.Iterator;
005import java.util.List;
006
007import org.apache.maven.plugin.AbstractMojo;
008import org.apache.maven.plugin.MojoExecutionException;
009
010/**
011 * Display help information on andromdapp-maven-plugin.<br/> Call <pre>  mvn andromdapp:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
012 *
013 * @version generated on Thu Sep 18 16:09:51 EDT 2014
014 * @author org.apache.maven.tools.plugin.generator.PluginHelpGenerator (version 2.9)
015 * @goal help
016 * @requiresProject false
017 * @threadSafe
018 */
019public class HelpMojo
020    extends AbstractMojo
021{
022    /**
023     * If <code>true</code>, display all settable properties for each goal.
024     * 
025     * @parameter expression="${detail}" default-value="false"
026     */
027    private boolean detail;
028
029    /**
030     * The name of the goal for which to show help. If unspecified, all goals will be displayed.
031     * 
032     * @parameter expression="${goal}"
033     */
034    private java.lang.String goal;
035
036    /**
037     * The maximum length of a display line, should be positive.
038     * 
039     * @parameter expression="${lineLength}" default-value="80"
040     */
041    private int lineLength;
042
043    /**
044     * The number of spaces per indentation level, should be positive.
045     * 
046     * @parameter expression="${indentSize}" default-value="2"
047     */
048    private int indentSize;
049
050
051    /** {@inheritDoc} */
052    public void execute()
053        throws MojoExecutionException
054    {
055        if ( lineLength <= 0 )
056        {
057            getLog().warn( "The parameter 'lineLength' should be positive, using '80' as default." );
058            lineLength = 80;
059        }
060        if ( indentSize <= 0 )
061        {
062            getLog().warn( "The parameter 'indentSize' should be positive, using '2' as default." );
063            indentSize = 2;
064        }
065
066        StringBuffer sb = new StringBuffer();
067
068        append( sb, "org.andromda.maven.plugins:andromdapp-maven-plugin:3.5-SNAPSHOT", 0 );
069        append( sb, "", 0 );
070
071        append( sb, "AndroMDA Application Generator Maven Plugin", 0 );
072        append( sb, "A plugin for running AndroMDA\'s AndroMDApp application generator to generate Maven2 AndroMDA powered applications.", 1 );
073        append( sb, "", 0 );
074
075        if ( goal == null || goal.length() <= 0 )
076        {
077            append( sb, "This plugin has 10 goals:", 0 );
078            append( sb, "", 0 );
079        }
080
081        if ( goal == null || goal.length() <= 0 || "build".equals( goal ) )
082        {
083            append( sb, "andromdapp:build", 0 );
084            append( sb, "A Mojo used for executing the build goals from the top level project.", 1 );
085            append( sb, "", 0 );
086            if ( detail )
087            {
088                append( sb, "Available parameters:", 1 );
089                append( sb, "", 0 );
090
091                append( sb, "baseDirectory", 2 );
092                append( sb, "(no description available)", 3 );
093                append( sb, "Expression: ${project.basedir}", 3 );
094                append( sb, "", 0 );
095
096                append( sb, "environmentVariablePrefix", 2 );
097                append( sb, "The prefix environment variables must have.", 3 );
098                append( sb, "Expression: env.", 3 );
099                append( sb, "", 0 );
100
101                append( sb, "executionProperties", 2 );
102                append( sb, "Any execution properties.", 3 );
103                append( sb, "", 0 );
104
105                append( sb, "goals", 2 );
106                append( sb, "The default module goals to execute.", 3 );
107                append( sb, "", 0 );
108
109                append( sb, "modules", 2 );
110                append( sb, "A comma separated list of modules to execute in the form: -Dmodules=mda,core,common or if you want to specify the goals to execute as well: -Dmodules=mda:[goal1+goal2+goal3],core:[goal1].", 3 );
111                append( sb, "Expression: ${modules}", 3 );
112                append( sb, "", 0 );
113
114                append( sb, "session", 2 );
115                append( sb, "(no description available)", 3 );
116                append( sb, "Expression: ${session}", 3 );
117                append( sb, "", 0 );
118
119                append( sb, "startConsole", 2 );
120                append( sb, "If defined starts the build console (i.e. keeps maven loaded and running)", 3 );
121                append( sb, "Expression: ${console}", 3 );
122                append( sb, "", 0 );
123            }
124        }
125
126        if ( goal == null || goal.length() <= 0 || "clean-structure".equals( goal ) )
127        {
128            append( sb, "andromdapp:clean-structure", 0 );
129            append( sb, "Removes the an AndroMDApp generated application structure.", 1 );
130            append( sb, "", 0 );
131            if ( detail )
132            {
133                append( sb, "Available parameters:", 1 );
134                append( sb, "", 0 );
135
136                append( sb, "configurationUri", 2 );
137                append( sb, "The URI to an optional AndroMDApp configuration file.", 3 );
138                append( sb, "Expression: ${configuration.uri}", 3 );
139                append( sb, "", 0 );
140
141                append( sb, "propertyFiles", 2 );
142                append( sb, "(no description available)", 3 );
143                append( sb, "Expression: ${project.build.filters}", 3 );
144                append( sb, "", 0 );
145
146                append( sb, "skip", 2 );
147                append( sb, "Set this to \'true\' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
148                append( sb, "Expression: ${maven.test.skip}", 3 );
149                append( sb, "", 0 );
150
151                append( sb, "skipProcessing", 2 );
152                append( sb, "Whether or not processing should be skipped (this is if you want to completely skip code generation, i.e. if code is already generated and you are creating the site from already generated source code).", 3 );
153                append( sb, "Expression: ${andromdapp.run.skip}", 3 );
154                append( sb, "", 0 );
155
156                append( sb, "skipTests", 2 );
157                append( sb, "Set this to \'true\' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
158                append( sb, "Expression: ${skipTests}", 3 );
159                append( sb, "", 0 );
160
161                append( sb, "testFailureIgnore (Default: false)", 2 );
162                append( sb, "Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
163                append( sb, "Expression: ${maven.test.failure.ignore}", 3 );
164                append( sb, "", 0 );
165            }
166        }
167
168        if ( goal == null || goal.length() <= 0 || "deploy".equals( goal ) )
169        {
170            append( sb, "andromdapp:deploy", 0 );
171            append( sb, "Provides the deployment of applications to a given directory.", 1 );
172            append( sb, "", 0 );
173            if ( detail )
174            {
175                append( sb, "Available parameters:", 1 );
176                append( sb, "", 0 );
177
178                append( sb, "deploy", 2 );
179                append( sb, "Indicates whether or not this plugin should perform the deploy.", 3 );
180                append( sb, "Expression: ${deploy}", 3 );
181                append( sb, "", 0 );
182
183                append( sb, "deployLocation", 2 );
184                append( sb, "The location (i.e. path) to deploy.", 3 );
185                append( sb, "Required: Yes", 3 );
186                append( sb, "", 0 );
187
188                append( sb, "excludes", 2 );
189                append( sb, "Any files to exclude in the deploy.", 3 );
190                append( sb, "", 0 );
191
192                append( sb, "includes", 2 );
193                append( sb, "Any additional files to include in the deploy liked datasource files etc (the files must reside in the project build directory). By default nothing besides the file artifact is deployed.", 3 );
194                append( sb, "", 0 );
195            }
196        }
197
198        if ( goal == null || goal.length() <= 0 || "eclipse".equals( goal ) )
199        {
200            append( sb, "andromdapp:eclipse", 0 );
201            append( sb, "Writes the necessary .classpath and .project files for a new eclipse application.", 1 );
202            append( sb, "", 0 );
203            if ( detail )
204            {
205                append( sb, "Available parameters:", 1 );
206                append( sb, "", 0 );
207
208                append( sb, "classpathArtifactTypes", 2 );
209                append( sb, "The artifact types which should be included in the generated Eclipse classpath.", 3 );
210                append( sb, "", 0 );
211
212                append( sb, "classpathMerge", 2 );
213                append( sb, "Allows non-generated configuration to be \'merged\' into the generated .classpath file.", 3 );
214                append( sb, "", 0 );
215
216                append( sb, "excludePoms", 2 );
217                append( sb, "Defines the POMs to exclude when generating the eclipse files.", 3 );
218                append( sb, "Expression: ${exclude.poms}", 3 );
219                append( sb, "", 0 );
220
221                append( sb, "excludes", 2 );
222                append( sb, "Defines the POMs to exclude when generating the eclipse files.", 3 );
223                append( sb, "", 0 );
224
225                append( sb, "includes", 2 );
226                append( sb, "Defines the POMs to include when generating the eclipse files.", 3 );
227                append( sb, "", 0 );
228
229                append( sb, "repositoryVariableName", 2 );
230                append( sb, "The name of the variable that will store the maven repository location.", 3 );
231                append( sb, "Expression: ${repository.variable.name}", 3 );
232                append( sb, "", 0 );
233
234                append( sb, "resolveTransitiveDependencies", 2 );
235                append( sb, "Whether or not transitive dependencies shall be included in any resources (i.e. .classpath that are generated by this mojo).", 3 );
236                append( sb, "Expression: ${resolveTransitiveDependencies}", 3 );
237                append( sb, "", 0 );
238
239                append( sb, "session", 2 );
240                append( sb, "(no description available)", 3 );
241                append( sb, "Expression: ${session}", 3 );
242                append( sb, "", 0 );
243
244                append( sb, "skipProcessing", 2 );
245                append( sb, "Whether or not processing should be skipped (this is if you just want to force AndroMDA not to run on your model).", 3 );
246                append( sb, "Expression: ${andromda.run.skip}", 3 );
247                append( sb, "", 0 );
248
249                append( sb, "variables", 2 );
250                append( sb, "(no description available)", 3 );
251                append( sb, "", 0 );
252            }
253        }
254
255        if ( goal == null || goal.length() <= 0 || "generate".equals( goal ) )
256        {
257            append( sb, "andromdapp:generate", 0 );
258            append( sb, "AndroMDA application generator Mojo.", 1 );
259            append( sb, "", 0 );
260            if ( detail )
261            {
262                append( sb, "Available parameters:", 1 );
263                append( sb, "", 0 );
264
265                append( sb, "configurationUri", 2 );
266                append( sb, "The URI to an optional AndroMDApp configuration file.", 3 );
267                append( sb, "Expression: ${configuration.uri}", 3 );
268                append( sb, "", 0 );
269
270                append( sb, "propertyFiles", 2 );
271                append( sb, "(no description available)", 3 );
272                append( sb, "Expression: ${project.build.filters}", 3 );
273                append( sb, "", 0 );
274
275                append( sb, "skip", 2 );
276                append( sb, "Set this to \'true\' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
277                append( sb, "Expression: ${maven.test.skip}", 3 );
278                append( sb, "", 0 );
279
280                append( sb, "skipProcessing", 2 );
281                append( sb, "Whether or not processing should be skipped (this is if you want to completely skip code generation, i.e. if code is already generated and you are creating the site from already generated source code).", 3 );
282                append( sb, "Expression: ${andromdapp.run.skip}", 3 );
283                append( sb, "", 0 );
284
285                append( sb, "skipTests", 2 );
286                append( sb, "Set this to \'true\' to skip running tests, but still compile them. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
287                append( sb, "Expression: ${skipTests}", 3 );
288                append( sb, "", 0 );
289
290                append( sb, "testFailureIgnore (Default: false)", 2 );
291                append( sb, "Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
292                append( sb, "Expression: ${maven.test.failure.ignore}", 3 );
293                append( sb, "", 0 );
294            }
295        }
296
297        if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
298        {
299            append( sb, "andromdapp:help", 0 );
300            append( sb, "Display help information on andromdapp-maven-plugin.\nCall\n\u00a0\u00a0mvn\u00a0andromdapp:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
301            append( sb, "", 0 );
302            if ( detail )
303            {
304                append( sb, "Available parameters:", 1 );
305                append( sb, "", 0 );
306
307                append( sb, "detail (Default: false)", 2 );
308                append( sb, "If true, display all settable properties for each goal.", 3 );
309                append( sb, "Expression: ${detail}", 3 );
310                append( sb, "", 0 );
311
312                append( sb, "goal", 2 );
313                append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
314                append( sb, "Expression: ${goal}", 3 );
315                append( sb, "", 0 );
316
317                append( sb, "indentSize (Default: 2)", 2 );
318                append( sb, "The number of spaces per indentation level, should be positive.", 3 );
319                append( sb, "Expression: ${indentSize}", 3 );
320                append( sb, "", 0 );
321
322                append( sb, "lineLength (Default: 80)", 2 );
323                append( sb, "The maximum length of a display line, should be positive.", 3 );
324                append( sb, "Expression: ${lineLength}", 3 );
325                append( sb, "", 0 );
326            }
327        }
328
329        if ( goal == null || goal.length() <= 0 || "instrument-scripts".equals( goal ) )
330        {
331            append( sb, "andromdapp:instrument-scripts", 0 );
332            append( sb, "Allows for the ScriptClassGenerator mojo to be invoked. on one or more given classes.", 1 );
333            append( sb, "", 0 );
334            if ( detail )
335            {
336                append( sb, "Available parameters:", 1 );
337                append( sb, "", 0 );
338
339                append( sb, "locations", 2 );
340                append( sb, "Defines the java files who\'s classes will be instrumented.", 3 );
341                append( sb, "Required: Yes", 3 );
342                append( sb, "", 0 );
343
344                append( sb, "scriptWrapper", 2 );
345                append( sb, "Defines the fully qualified class name of the script wrapper implementation.", 3 );
346                append( sb, "Required: Yes", 3 );
347                append( sb, "", 0 );
348            }
349        }
350
351        if ( goal == null || goal.length() <= 0 || "link".equals( goal ) )
352        {
353            append( sb, "andromdapp:link", 0 );
354            append( sb, "Basically post processes a previously built ear and replaces any war artifacts with symbolic links and then symbolic links the ear to the deploy directory so that we don\'t have to redeploy an ear in order to make jsp changes.", 1 );
355            append( sb, "", 0 );
356            if ( detail )
357            {
358                append( sb, "Available parameters:", 1 );
359                append( sb, "", 0 );
360
361                append( sb, "deployLocation", 2 );
362                append( sb, "The location in which to link the exploded ear.", 3 );
363                append( sb, "Expression: ${env.JBOSS_HOME}/server/default/deploy", 3 );
364                append( sb, "", 0 );
365
366                append( sb, "rootProjectLimit", 2 );
367                append( sb, "The number of levels allowed to travel up before we get to the \'root project\' (i.e. this will prevent the system from attempting to get parent project that aren\'t really part of the direct project).", 3 );
368                append( sb, "Expression: 1", 3 );
369                append( sb, "", 0 );
370            }
371        }
372
373        if ( goal == null || goal.length() <= 0 || "schema".equals( goal ) )
374        {
375            append( sb, "andromdapp:schema", 0 );
376            append( sb, "Provides the ability to drop database schemas.", 1 );
377            append( sb, "", 0 );
378            if ( detail )
379            {
380                append( sb, "Available parameters:", 1 );
381                append( sb, "", 0 );
382
383                append( sb, "executeScripts", 2 );
384                append( sb, "Whether or not scripts should be executed (if this is set to false, they will only be generated, but not executed).", 3 );
385                append( sb, "Expression: ${executeScripts}", 3 );
386                append( sb, "", 0 );
387
388                append( sb, "jdbcConnectionUrl", 2 );
389                append( sb, "The JDBC connection URL.", 3 );
390                append( sb, "Required: Yes", 3 );
391                append( sb, "", 0 );
392
393                append( sb, "jdbcDriver", 2 );
394                append( sb, "The name of the JDBC driver class.", 3 );
395                append( sb, "Required: Yes", 3 );
396                append( sb, "", 0 );
397
398                append( sb, "jdbcDriverJar", 2 );
399                append( sb, "The jar containing the JDBC driver.", 3 );
400                append( sb, "Required: Yes", 3 );
401                append( sb, "", 0 );
402
403                append( sb, "jdbcPassword", 2 );
404                append( sb, "The JDBC password for the database.", 3 );
405                append( sb, "", 0 );
406
407                append( sb, "jdbcUsername", 2 );
408                append( sb, "The JDBC username for the database.", 3 );
409                append( sb, "Required: Yes", 3 );
410                append( sb, "", 0 );
411
412                append( sb, "pluginArtifacts", 2 );
413                append( sb, "(no description available)", 3 );
414                append( sb, "Required: Yes", 3 );
415                append( sb, "Expression: ${plugin.artifacts}", 3 );
416                append( sb, "", 0 );
417
418                append( sb, "properties", 2 );
419                append( sb, "The properties that can be passed to the schema task.", 3 );
420                append( sb, "", 0 );
421
422                append( sb, "propertyFiles", 2 );
423                append( sb, "Any property files that should be loaded into the schema properties.", 3 );
424                append( sb, "", 0 );
425
426                append( sb, "scripts", 2 );
427                append( sb, "Defines the location(s) of any SQL scripts to be executed.", 3 );
428                append( sb, "", 0 );
429
430                append( sb, "tasks", 2 );
431                append( sb, "The schema task to execute (create, drop, update, validate)", 3 );
432                append( sb, "Expression: ${tasks}", 3 );
433                append( sb, "", 0 );
434
435                append( sb, "taskType", 2 );
436                append( sb, "The type of the create schema task to execute.", 3 );
437                append( sb, "Required: Yes", 3 );
438                append( sb, "Expression: hibernate", 3 );
439                append( sb, "", 0 );
440            }
441        }
442
443        if ( goal == null || goal.length() <= 0 || "undeploy".equals( goal ) )
444        {
445            append( sb, "andromdapp:undeploy", 0 );
446            append( sb, "Provides the undeployment of applications from a given directory.", 1 );
447            append( sb, "", 0 );
448            if ( detail )
449            {
450                append( sb, "Available parameters:", 1 );
451                append( sb, "", 0 );
452
453                append( sb, "deployLocation", 2 );
454                append( sb, "The location (i.e. path) to deploy.", 3 );
455                append( sb, "Required: Yes", 3 );
456                append( sb, "", 0 );
457            }
458        }
459
460        if ( getLog().isInfoEnabled() )
461        {
462            getLog().info( sb.toString() );
463        }
464    }
465
466    /**
467     * <p>Repeat a String <code>n</code> times to form a new string.</p>
468     *
469     * @param str String to repeat
470     * @param repeat number of times to repeat str
471     * @return String with repeated String
472     * @throws NegativeArraySizeException if <code>repeat < 0</code>
473     * @throws NullPointerException if str is <code>null</code>
474     */
475    private static String repeat( String str, int repeat )
476    {
477        StringBuffer buffer = new StringBuffer( repeat * str.length() );
478
479        for ( int i = 0; i < repeat; i++ )
480        {
481            buffer.append( str );
482        }
483
484        return buffer.toString();
485    }
486
487    /** 
488     * Append a description to the buffer by respecting the indentSize and lineLength parameters.
489     * <b>Note</b>: The last character is always a new line.
490     * 
491     * @param sb The buffer to append the description, not <code>null</code>.
492     * @param description The description, not <code>null</code>.
493     * @param indent The base indentation level of each line, must not be negative.
494     */
495    private void append( StringBuffer sb, String description, int indent )
496    {
497        for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
498        {
499            sb.append( it.next().toString() ).append( '\n' );
500        }
501    }
502
503    /** 
504     * Splits the specified text into lines of convenient display length.
505     * 
506     * @param text The text to split into lines, must not be <code>null</code>.
507     * @param indent The base indentation level of each line, must not be negative.
508     * @param indentSize The size of each indentation, must not be negative.
509     * @param lineLength The length of the line, must not be negative.
510     * @return The sequence of display lines, never <code>null</code>.
511     * @throws NegativeArraySizeException if <code>indent < 0</code>
512     */
513    private static List toLines( String text, int indent, int indentSize, int lineLength )
514    {
515        List lines = new ArrayList();
516
517        String ind = repeat( "\t", indent );
518        String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
519        for ( int i = 0; i < plainLines.length; i++ )
520        {
521            toLines( lines, ind + plainLines[i], indentSize, lineLength );
522        }
523
524        return lines;
525    }
526
527    /** 
528     * Adds the specified line to the output sequence, performing line wrapping if necessary.
529     * 
530     * @param lines The sequence of display lines, must not be <code>null</code>.
531     * @param line The line to add, must not be <code>null</code>.
532     * @param indentSize The size of each indentation, must not be negative.
533     * @param lineLength The length of the line, must not be negative.
534     */
535    private static void toLines( List lines, String line, int indentSize, int lineLength )
536    {
537        int lineIndent = getIndentLevel( line );
538        StringBuffer buf = new StringBuffer( 256 );
539        String[] tokens = line.split( " +" );
540        for ( int i = 0; i < tokens.length; i++ )
541        {
542            String token = tokens[i];
543            if ( i > 0 )
544            {
545                if ( buf.length() + token.length() >= lineLength )
546                {
547                    lines.add( buf.toString() );
548                    buf.setLength( 0 );
549                    buf.append( repeat( " ", lineIndent * indentSize ) );
550                }
551                else
552                {
553                    buf.append( ' ' );
554                }
555            }
556            for ( int j = 0; j < token.length(); j++ )
557            {
558                char c = token.charAt( j );
559                if ( c == '\t' )
560                {
561                    buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
562                }
563                else if ( c == '\u00A0' )
564                {
565                    buf.append( ' ' );
566                }
567                else
568                {
569                    buf.append( c );
570                }
571            }
572        }
573        lines.add( buf.toString() );
574    }
575
576    /** 
577     * Gets the indentation level of the specified line.
578     * 
579     * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
580     * @return The indentation level of the line.
581     */
582    private static int getIndentLevel( String line )
583    {
584        int level = 0;
585        for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
586        {
587            level++;
588        }
589        for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
590        {
591            if ( line.charAt( i ) == '\t' )
592            {
593                level++;
594                break;
595            }
596        }
597        return level;
598    }
599}