001package org.andromda.maven.plugin.cartridge; 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-cartridge-plugin.<br/> Call <pre> mvn andromda-cartridge:help -Ddetail=true -Dgoal=<goal-name></pre> to display parameter details. 012 * 013 * @version generated on Thu Sep 18 16:26:58 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-cartridge-plugin:3.5-SNAPSHOT", 0 ); 069 append( sb, "", 0 ); 070 071 append( sb, "AndroMDA Cartridge Maven Plugin", 0 ); 072 append( sb, "A Maven plugin for performing AndroMDA cartridge related tasks (such as running cartridge tests).", 1 ); 073 append( sb, "", 0 ); 074 075 if ( goal == null || goal.length() <= 0 ) 076 { 077 append( sb, "This plugin has 3 goals:", 0 ); 078 append( sb, "", 0 ); 079 } 080 081 if ( goal == null || goal.length() <= 0 || "help".equals( goal ) ) 082 { 083 append( sb, "andromda-cartridge:help", 0 ); 084 append( sb, "Display help information on andromda-cartridge-plugin.\nCall\n\u00a0\u00a0mvn\u00a0andromda-cartridge: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-cartridge: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, "actualDirectory", 2 ); 124 append( sb, "Specifies the directory that contains the \'actual\' output (meaning the output that was currently generated)", 3 ); 125 append( sb, "Required: Yes", 3 ); 126 append( sb, "Expression: ${project.build.directory}/cartridge-test/actual", 3 ); 127 append( sb, "", 0 ); 128 129 append( sb, "binaryOutputSuffixes", 2 ); 130 append( sb, "Defines the extensions of binary files, binary files are checked for presence and equality, however they aren\'t compared as strings, like every other file.", 3 ); 131 append( sb, "Expression: jpg,jpeg,gif,png,jar,zip", 3 ); 132 append( sb, "", 0 ); 133 134 append( sb, "configurationUri", 2 ); 135 append( sb, "This is the URI to the AndroMDA configuration file.", 3 ); 136 append( sb, "Required: Yes", 3 ); 137 append( sb, "Expression: file:${basedir}/conf/test/andromdaUML2.xml", 3 ); 138 append( sb, "", 0 ); 139 140 append( sb, "expectedDirectory", 2 ); 141 append( sb, "Specifies the directory that contains the \'expected\' output.", 3 ); 142 append( sb, "Required: Yes", 3 ); 143 append( sb, "Expression: ${project.build.directory}/cartridge-test/expected", 3 ); 144 append( sb, "", 0 ); 145 146 append( sb, "expectedOutputArchive", 2 ); 147 append( sb, "The location of the archive storing the expected output.", 3 ); 148 append( sb, "Required: Yes", 3 ); 149 append( sb, "Expression: ${basedir}/src/test/expected/cartridge-outputUML2.zip", 3 ); 150 append( sb, "", 0 ); 151 152 append( sb, "lastModifiedCheck", 2 ); 153 append( sb, "Set this to \'true\' to skip code generation if code has not changed since the latest model date.", 3 ); 154 append( sb, "Expression: ${lastModifiedCheck}", 3 ); 155 append( sb, "", 0 ); 156 157 append( sb, "propertyFiles", 2 ); 158 append( sb, "(no description available)", 3 ); 159 append( sb, "Expression: ${project.build.filters}", 3 ); 160 append( sb, "", 0 ); 161 162 append( sb, "reportDirectory", 2 ); 163 append( sb, "Base directory to which the cartridge test report is written", 3 ); 164 append( sb, "Expression: ${project.build.directory}/cartridge-test/reports", 3 ); 165 append( sb, "", 0 ); 166 167 append( sb, "skip", 2 ); 168 append( sb, "Set this to \'true\' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 ); 169 append( sb, "Expression: ${maven.test.skip}", 3 ); 170 append( sb, "", 0 ); 171 172 append( sb, "skipTests", 2 ); 173 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 ); 174 append( sb, "Expression: ${skipTests}", 3 ); 175 append( sb, "", 0 ); 176 177 append( sb, "testFailureIgnore (Default: false)", 2 ); 178 append( sb, "Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 ); 179 append( sb, "Expression: ${maven.test.failure.ignore}", 3 ); 180 append( sb, "", 0 ); 181 } 182 } 183 184 if ( goal == null || goal.length() <= 0 || "update".equals( goal ) ) 185 { 186 append( sb, "andromda-cartridge:update", 0 ); 187 append( sb, "Updates the cartridge expected output with the current cartridge output. Invoke it with mvn andromda-cartridge:update when you are inside the cartridge root directory.", 1 ); 188 append( sb, "", 0 ); 189 if ( detail ) 190 { 191 append( sb, "Available parameters:", 1 ); 192 append( sb, "", 0 ); 193 194 append( sb, "actualDirectory", 2 ); 195 append( sb, "Specifies the directory that contains the \'actual\' output (meaning the output that was currently generated)", 3 ); 196 append( sb, "Required: Yes", 3 ); 197 append( sb, "Expression: ${project.build.directory}/cartridge-test/actual", 3 ); 198 append( sb, "", 0 ); 199 200 append( sb, "binaryOutputSuffixes", 2 ); 201 append( sb, "Defines the extensions of binary files, binary files are checked for presence and equality, however they aren\'t compared as strings, like every other file.", 3 ); 202 append( sb, "Expression: jpg,jpeg,gif,png,jar,zip", 3 ); 203 append( sb, "", 0 ); 204 205 append( sb, "configurationUri", 2 ); 206 append( sb, "This is the URI to the AndroMDA configuration file.", 3 ); 207 append( sb, "Required: Yes", 3 ); 208 append( sb, "Expression: file:${basedir}/conf/test/andromdaUML2.xml", 3 ); 209 append( sb, "", 0 ); 210 211 append( sb, "expectedDirectory", 2 ); 212 append( sb, "Specifies the directory that contains the \'expected\' output.", 3 ); 213 append( sb, "Required: Yes", 3 ); 214 append( sb, "Expression: ${project.build.directory}/cartridge-test/expected", 3 ); 215 append( sb, "", 0 ); 216 217 append( sb, "expectedOutputArchive", 2 ); 218 append( sb, "The location of the archive storing the expected output.", 3 ); 219 append( sb, "Required: Yes", 3 ); 220 append( sb, "Expression: ${basedir}/src/test/expected/cartridge-outputUML2.zip", 3 ); 221 append( sb, "", 0 ); 222 223 append( sb, "lastModifiedCheck", 2 ); 224 append( sb, "Set this to \'true\' to skip code generation if code has not changed since the latest model date.", 3 ); 225 append( sb, "Expression: ${lastModifiedCheck}", 3 ); 226 append( sb, "", 0 ); 227 228 append( sb, "propertyFiles", 2 ); 229 append( sb, "(no description available)", 3 ); 230 append( sb, "Expression: ${project.build.filters}", 3 ); 231 append( sb, "", 0 ); 232 233 append( sb, "reportDirectory", 2 ); 234 append( sb, "Base directory to which the cartridge test report is written", 3 ); 235 append( sb, "Expression: ${project.build.directory}/cartridge-test/reports", 3 ); 236 append( sb, "", 0 ); 237 238 append( sb, "skip", 2 ); 239 append( sb, "Set this to \'true\' to bypass cartridge tests entirely. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 ); 240 append( sb, "Expression: ${maven.test.skip}", 3 ); 241 append( sb, "", 0 ); 242 243 append( sb, "skipTests", 2 ); 244 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 ); 245 append( sb, "Expression: ${skipTests}", 3 ); 246 append( sb, "", 0 ); 247 248 append( sb, "testFailureIgnore (Default: false)", 2 ); 249 append( sb, "Set this to true to ignore a failure during testing. Its use is NOT RECOMMENDED, but quite convenient on occasion.", 3 ); 250 append( sb, "Expression: ${maven.test.failure.ignore}", 3 ); 251 append( sb, "", 0 ); 252 } 253 } 254 255 if ( getLog().isInfoEnabled() ) 256 { 257 getLog().info( sb.toString() ); 258 } 259 } 260 261 /** 262 * <p>Repeat a String <code>n</code> times to form a new string.</p> 263 * 264 * @param str String to repeat 265 * @param repeat number of times to repeat str 266 * @return String with repeated String 267 * @throws NegativeArraySizeException if <code>repeat < 0</code> 268 * @throws NullPointerException if str is <code>null</code> 269 */ 270 private static String repeat( String str, int repeat ) 271 { 272 StringBuffer buffer = new StringBuffer( repeat * str.length() ); 273 274 for ( int i = 0; i < repeat; i++ ) 275 { 276 buffer.append( str ); 277 } 278 279 return buffer.toString(); 280 } 281 282 /** 283 * Append a description to the buffer by respecting the indentSize and lineLength parameters. 284 * <b>Note</b>: The last character is always a new line. 285 * 286 * @param sb The buffer to append the description, not <code>null</code>. 287 * @param description The description, not <code>null</code>. 288 * @param indent The base indentation level of each line, must not be negative. 289 */ 290 private void append( StringBuffer sb, String description, int indent ) 291 { 292 for ( Iterator it = toLines( description, indent, indentSize, lineLength ).iterator(); it.hasNext(); ) 293 { 294 sb.append( it.next().toString() ).append( '\n' ); 295 } 296 } 297 298 /** 299 * Splits the specified text into lines of convenient display length. 300 * 301 * @param text The text to split into lines, must not be <code>null</code>. 302 * @param indent The base indentation level of each line, must not be negative. 303 * @param indentSize The size of each indentation, must not be negative. 304 * @param lineLength The length of the line, must not be negative. 305 * @return The sequence of display lines, never <code>null</code>. 306 * @throws NegativeArraySizeException if <code>indent < 0</code> 307 */ 308 private static List toLines( String text, int indent, int indentSize, int lineLength ) 309 { 310 List lines = new ArrayList(); 311 312 String ind = repeat( "\t", indent ); 313 String[] plainLines = text.split( "(\r\n)|(\r)|(\n)" ); 314 for ( int i = 0; i < plainLines.length; i++ ) 315 { 316 toLines( lines, ind + plainLines[i], indentSize, lineLength ); 317 } 318 319 return lines; 320 } 321 322 /** 323 * Adds the specified line to the output sequence, performing line wrapping if necessary. 324 * 325 * @param lines The sequence of display lines, must not be <code>null</code>. 326 * @param line The line to add, must not be <code>null</code>. 327 * @param indentSize The size of each indentation, must not be negative. 328 * @param lineLength The length of the line, must not be negative. 329 */ 330 private static void toLines( List lines, String line, int indentSize, int lineLength ) 331 { 332 int lineIndent = getIndentLevel( line ); 333 StringBuffer buf = new StringBuffer( 256 ); 334 String[] tokens = line.split( " +" ); 335 for ( int i = 0; i < tokens.length; i++ ) 336 { 337 String token = tokens[i]; 338 if ( i > 0 ) 339 { 340 if ( buf.length() + token.length() >= lineLength ) 341 { 342 lines.add( buf.toString() ); 343 buf.setLength( 0 ); 344 buf.append( repeat( " ", lineIndent * indentSize ) ); 345 } 346 else 347 { 348 buf.append( ' ' ); 349 } 350 } 351 for ( int j = 0; j < token.length(); j++ ) 352 { 353 char c = token.charAt( j ); 354 if ( c == '\t' ) 355 { 356 buf.append( repeat( " ", indentSize - buf.length() % indentSize ) ); 357 } 358 else if ( c == '\u00A0' ) 359 { 360 buf.append( ' ' ); 361 } 362 else 363 { 364 buf.append( c ); 365 } 366 } 367 } 368 lines.add( buf.toString() ); 369 } 370 371 /** 372 * Gets the indentation level of the specified line. 373 * 374 * @param line The line whose indentation level should be retrieved, must not be <code>null</code>. 375 * @return The indentation level of the line. 376 */ 377 private static int getIndentLevel( String line ) 378 { 379 int level = 0; 380 for ( int i = 0; i < line.length() && line.charAt( i ) == '\t'; i++ ) 381 { 382 level++; 383 } 384 for ( int i = level + 1; i <= level + 4 && i < line.length(); i++ ) 385 { 386 if ( line.charAt( i ) == '\t' ) 387 { 388 level++; 389 break; 390 } 391 } 392 return level; 393 } 394}