001package org.andromda.maven.plugin.translationlibrary;
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 andromda-translation-library-plugin.<br/> Call <pre>  mvn andromda-translation-library:help -Ddetail=true -Dgoal=&lt;goal-name&gt;</pre> to display parameter details.
012 *
013 * @version generated on Thu Sep 18 16:29:14 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:andromda-translation-library-plugin:3.5-SNAPSHOT", 0 );
069        append( sb, "", 0 );
070
071        append( sb, "AndroMDA Translation Library Maven Plugin", 0 );
072        append( sb, "A Maven plugin for performing AndroMDA translation-library related tasks (such as running translation-library tests).", 1 );
073        append( sb, "", 0 );
074
075        if ( goal == null || goal.length() <= 0 )
076        {
077            append( sb, "This plugin has 2 goals:", 0 );
078            append( sb, "", 0 );
079        }
080
081        if ( goal == null || goal.length() <= 0 || "help".equals( goal ) )
082        {
083            append( sb, "andromda-translation-library:help", 0 );
084            append( sb, "Display help information on andromda-translation-library-plugin.\nCall\n\u00a0\u00a0mvn\u00a0andromda-translation-library:help\u00a0-Ddetail=true\u00a0-Dgoal=<goal-name>\nto display parameter details.", 1 );
085            append( sb, "", 0 );
086            if ( detail )
087            {
088                append( sb, "Available parameters:", 1 );
089                append( sb, "", 0 );
090
091                append( sb, "detail (Default: false)", 2 );
092                append( sb, "If true, display all settable properties for each goal.", 3 );
093                append( sb, "Expression: ${detail}", 3 );
094                append( sb, "", 0 );
095
096                append( sb, "goal", 2 );
097                append( sb, "The name of the goal for which to show help. If unspecified, all goals will be displayed.", 3 );
098                append( sb, "Expression: ${goal}", 3 );
099                append( sb, "", 0 );
100
101                append( sb, "indentSize (Default: 2)", 2 );
102                append( sb, "The number of spaces per indentation level, should be positive.", 3 );
103                append( sb, "Expression: ${indentSize}", 3 );
104                append( sb, "", 0 );
105
106                append( sb, "lineLength (Default: 80)", 2 );
107                append( sb, "The maximum length of a display line, should be positive.", 3 );
108                append( sb, "Expression: ${lineLength}", 3 );
109                append( sb, "", 0 );
110            }
111        }
112
113        if ( goal == null || goal.length() <= 0 || "test".equals( goal ) )
114        {
115            append( sb, "andromda-translation-library:test", 0 );
116            append( sb, "Provides the ability to compare cartridge output with existing output.", 1 );
117            append( sb, "", 0 );
118            if ( detail )
119            {
120                append( sb, "Available parameters:", 1 );
121                append( sb, "", 0 );
122
123                append( sb, "configurationUri", 2 );
124                append( sb, "This is the URI to the AndroMDA configuration file.", 3 );
125                append( sb, "Required: Yes", 3 );
126                append( sb, "Expression: file:${basedir}/conf/test/andromda.xml", 3 );
127                append( sb, "", 0 );
128
129                append( sb, "propertyFiles", 2 );
130                append( sb, "(no description available)", 3 );
131                append( sb, "Expression: ${project.build.filters}", 3 );
132                append( sb, "", 0 );
133
134                append( sb, "reportDirectory", 2 );
135                append( sb, "Base directory to which the cartridge test report is written", 3 );
136                append( sb, "Expression: ${project.build.directory}/translation-library-test/reports", 3 );
137                append( sb, "", 0 );
138
139                append( sb, "skipTranslation (Default: false)", 2 );
140                append( sb, "Set this to \'true\' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 );
141                append( sb, "Expression: ${andromda.translation.test.skip}", 3 );
142                append( sb, "", 0 );
143
144                append( sb, "traceExpression", 2 );
145                append( sb, "Whether or not the expression shall be \'traced\' (i.e. the TraceTranslator will run instead of the specified translator). This is helpful, in allowing us to see which expressions are being parsed in what order, etc.", 3 );
146                append( sb, "Expression: ${trace.expression}", 3 );
147                append( sb, "", 0 );
148
149                append( sb, "translationName", 2 );
150                append( sb, "When specified, only this translation will be tested (If more than one TestTranslation-* file is found).", 3 );
151                append( sb, "Expression: ${translation.name}", 3 );
152                append( sb, "", 0 );
153            }
154        }
155
156        if ( getLog().isInfoEnabled() )
157        {
158            getLog().info( sb.toString() );
159        }
160    }
161
162    /**
163     * <p>Repeat a String <code>n</code> times to form a new string.</p>
164     *
165     * @param str String to repeat
166     * @param repeat number of times to repeat str
167     * @return String with repeated String
168     * @throws NegativeArraySizeException if <code>repeat < 0</code>
169     * @throws NullPointerException if str is <code>null</code>
170     */
171    private static String repeat( String str, int repeat )
172    {
173        StringBuffer buffer = new StringBuffer( repeat * str.length() );
174
175        for ( int i = 0; i < repeat; i++ )
176        {
177            buffer.append( str );
178        }
179
180        return buffer.toString();
181    }
182
183    /** 
184     * Append a description to the buffer by respecting the indentSize and lineLength parameters.
185     * <b>Note</b>: The last character is always a new line.
186     * 
187     * @param sb The buffer to append the description, not <code>null</code>.
188     * @param description The description, not <code>null</code>.
189     * @param indent The base indentation level of each line, must not be negative.
190     */
191    private void append( StringBuffer sb, String description, int indent )
192    {
193        for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); )
194        {
195            sb.append( it.next().toString() ).append( '\n' );
196        }
197    }
198
199    /** 
200     * Splits the specified text into lines of convenient display length.
201     * 
202     * @param text The text to split into lines, must not be <code>null</code>.
203     * @param indent The base indentation level of each line, must not be negative.
204     * @param indentSize The size of each indentation, must not be negative.
205     * @param lineLength The length of the line, must not be negative.
206     * @return The sequence of display lines, never <code>null</code>.
207     * @throws NegativeArraySizeException if <code>indent < 0</code>
208     */
209    private static List toLines( String text, int indent, int indentSize, int lineLength )
210    {
211        List lines = new ArrayList();
212
213        String ind = repeat( "\t", indent );
214        String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" );
215        for ( int i = 0; i < plainLines.length; i++ )
216        {
217            toLines( lines, ind + plainLines[i], indentSize, lineLength );
218        }
219
220        return lines;
221    }
222
223    /** 
224     * Adds the specified line to the output sequence, performing line wrapping if necessary.
225     * 
226     * @param lines The sequence of display lines, must not be <code>null</code>.
227     * @param line The line to add, must not be <code>null</code>.
228     * @param indentSize The size of each indentation, must not be negative.
229     * @param lineLength The length of the line, must not be negative.
230     */
231    private static void toLines( List lines, String line, int indentSize, int lineLength )
232    {
233        int lineIndent = getIndentLevel( line );
234        StringBuffer buf = new StringBuffer( 256 );
235        String[] tokens = line.split( " +" );
236        for ( int i = 0; i < tokens.length; i++ )
237        {
238            String token = tokens[i];
239            if ( i > 0 )
240            {
241                if ( buf.length() + token.length() >= lineLength )
242                {
243                    lines.add( buf.toString() );
244                    buf.setLength( 0 );
245                    buf.append( repeat( " ", lineIndent * indentSize ) );
246                }
247                else
248                {
249                    buf.append( ' ' );
250                }
251            }
252            for ( int j = 0; j < token.length(); j++ )
253            {
254                char c = token.charAt( j );
255                if ( c == '\t' )
256                {
257                    buf.append( repeat( " ", indentSize - buf.length() % indentSize ) );
258                }
259                else if ( c == '\u00A0' )
260                {
261                    buf.append( ' ' );
262                }
263                else
264                {
265                    buf.append( c );
266                }
267            }
268        }
269        lines.add( buf.toString() );
270    }
271
272    /** 
273     * Gets the indentation level of the specified line.
274     * 
275     * @param line The line whose indentation level should be retrieved, must not be <code>null</code>.
276     * @return The indentation level of the line.
277     */
278    private static int getIndentLevel( String line )
279    {
280        int level = 0;
281        for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ )
282        {
283            level++;
284        }
285        for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ )
286        {
287            if ( line.charAt( i ) == '\t' )
288            {
289                level++;
290                break;
291            }
292        }
293        return level;
294    }
295}