001package Torello.Java.Build; 002 003import Apache.CLI.*; 004 005import static Torello.Java.C.*; 006 007import Torello.Java.UnreachableError; 008import Torello.Java.StrCmpr; 009 010import Torello.Java.ReadOnly.ReadOnlyList; 011import Torello.Java.ReadOnly.ReadOnlyArrayList; 012 013import java.util.ArrayList; 014import java.util.List; 015import java.util.stream.Stream; 016import java.io.File; 017 018/** 019 * This data class is generated by parsing the Command-Line Input to a Builder Invocation, and it 020 * contains the settings that were extrapolated by the Apache CLI Parser. When a {@link Builder} 021 * instance is created, its constructor requires that a Java {@code `String[] argv`} array be 022 * included as a Constructor-Parameter. The provided {@code String[]}-Array is used to build an 023 * instance of this class. 024 * 025 * <BR /><BR />The data contained as fields of this class is all declared {@code public} and also 026 * {@code ReadOnly} or {@code final}. The instance generated from the Command-Line Input (CLI) 027 * parser is available as a {@code public} and {@code final} field of the {@link Builder} instance 028 * field {@link Builder#cli Torello.Java.Build.Builder.cli}; 029 * 030 * <BR /><BR />This class does not offer any public constructors, nor any public methods. It is 031 * automatically built by class {@code Builder}, which has package-level access to this class' sole 032 * constructor. 033 * 034 * <EMBED CLASS='external-html' DATA-FILE-ID=CLI_SWITCHES> 035 */ 036public class CLI 037{ 038 // ******************************************************************************************** 039 // ******************************************************************************************** 040 // Fields 041 // ******************************************************************************************** 042 // ******************************************************************************************** 043 044 045 public final String MENU_CHOICE; 046 public final boolean INCLUDE_JAR_IN_CP; 047 public final boolean SKIP_REMOVE_GCS_FILES; 048 public final boolean JAR_ONLY; 049 public final boolean INCLUDE_EARLY_DEV_PACKAGES; 050 public final boolean toReleaseOrDeveloper; 051 public final boolean QUICKER_BUILD; 052 public final boolean OVERRIDE_TOGGLE_USE_XLINT_SWITCH; 053 public final boolean OVERRIDE_TOGGLE_USE_XDIAGS_SWITCH; 054 public final String GCS_DIR; 055 056 // Option #1 and #21. Note, it was decided both of these shall be 'null' instead of 057 // empty-lists (when they would otherwise be empty-lists) 058 059 public final ReadOnlyList<BuildPackage> userSpecifiedPackages; 060 public final ReadOnlyList<String> userProvidedNickNames; 061 062 063 // ******************************************************************************************** 064 // ******************************************************************************************** 065 // Main-Menu Options-Group 066 // ******************************************************************************************** 067 // ******************************************************************************************** 068 069 070 // This generates an "OptionGroup" that contains all of the choices for the Main-Menu 071 // Exactly one of these options must be chosen by the user. 072 // 073 // If zero **OR** more than one is chosen, then the CLI-Constructor will throw an exception and 074 // print an error message 075 // 076 // The Options Include: 077 // * 8 Individual Build-Steps 078 // * 3 Complete-Build Composite-Steps (These perform steps 1 through 7/8) 079 // * 2 Developer-Build Composite-Steps (These perform a subset of steps 1 - 8) 080 081 private static OptionGroup mainOptions() 082 { 083 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 084 // Primary Build-Step Options 085 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 086 087 final Option javac = Option 088 .builder ("1") 089 .required (false) 090 .desc ("Build Stage 1: Java-Compiler") 091 .longOpt ("javac") 092 .hasArgs () 093 .optionalArg (true) 094 .valueSeparator (' ') 095 .argName ("PackageNickNames") 096 .build(); 097 098 final Option javaDoc = Option 099 .builder ("2") 100 .required (false) 101 .desc ("Build Stage 2: Standard 'javadoc' Tool") 102 .longOpt ("javadoc") 103 .hasArg (false) 104 .build(); 105 106 final Option jdu = Option 107 .builder ("3") 108 .required (false) 109 .desc ("Build Stage 3: Torello Java-Doc Upgrader") 110 .longOpt ("jdu") 111 .hasArg (false) 112 .build(); 113 114 final Option tarJar = Option 115 .builder ("4") 116 .required (false) 117 .desc ("Build Stage 4, Archive-Files") 118 .longOpt ("tarjar") 119 .optionalArg (true) // "JARONLY" 120 .valueSeparator (' ') 121 .argName ("JARONLY") 122 .build(); 123 124 125 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 126 // Sync-Step Options 127 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 128 129 final Option syncJavaDoc = Option 130 .builder ("5") 131 .required (false) 132 .desc ("Build Stage 5: Sync 'javadoc/'") 133 .longOpt ("syncJavaDoc") 134 .hasArg (false) 135 .build(); 136 137 final Option syncTarJar = Option 138 .builder ("6") 139 .required (false) 140 .desc ("Build Stage 6: Sync Tar & Jar") 141 .longOpt ("syncTarJar") 142 .hasArg (false) 143 .build(); 144 145 final Option syncLogs = Option 146 .builder ("7") 147 .required (false) 148 .desc ("Build Stage 7: Sync Log-Files") 149 .longOpt ("syncLogs") 150 .hasArg (false) 151 .build(); 152 153 final Option setMaxAge = Option 154 .builder ("8") 155 .required (false) 156 .desc ("Build Stage 8: Set Max-Age Browser-Cache") 157 .longOpt ("setMaxAge") 158 .hasArg (false) 159 .build(); 160 161 162 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 163 // Composite-Step / Complete-Build Options 164 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 165 166 final Option buildRel = Option 167 .builder ("cb1") 168 .required (false) 169 .desc ("Complete Build: STEPS 2 to 7. Sync-To: GCP-Release") 170 .longOpt ("buildRel") 171 .hasArg (false) 172 .build(); 173 174 final Option buildDevSMA = Option 175 .builder ("cb2") 176 .required (false) 177 .desc ("Complete Build: STEPS 2 to 8. Sync-To: GCP-Developer") 178 .longOpt ("buildDevSMA") 179 .hasArg (false) 180 .build(); 181 182 final Option buildDev = Option 183 .builder ("cb3") 184 .required (false) 185 .desc ("Complete Build: STEPS 2 to 7. Sync-To: GCP-Developer") 186 .longOpt ("buildDev") 187 .hasArg (false) 188 .build(); 189 190 191 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 192 // Partial Debugging / Developer Build 193 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 194 195 final Option partialAll = Option 196 .builder ("pb1") 197 .required (false) 198 .desc ("Partial-Debuging Build: STEPS 2 & 3. (Doc Only)") 199 .longOpt ("partialAll") 200 .hasArg (false) 201 .build(); 202 203 final Option partialSome = Option 204 .builder ("pb2") 205 .required (false) 206 .desc ("Partial-Debuging Build: STEPS 2, 3, 5, and 8. To: GCP-Developer") 207 .longOpt ("partialSome") 208 .hasArgs () 209 .optionalArg (true) 210 .valueSeparator (' ') 211 .argName ("PackageNickNames") 212 .build(); 213 214 215 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 216 // Run Links Checker 217 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 218 219 final Option linksCheck = Option 220 .builder ("LC") 221 .required (false) 222 .desc ("Links Checker Build") 223 .longOpt ("linksCheck") 224 .hasArg (false) 225 .build(); 226 227 228 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 229 // INSERT ALL INTO THE "OptionGroup" ... And return that instance 230 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 231 232 final OptionGroup group = new OptionGroup(); 233 234 group.setRequired(true); 235 group 236 // Primary Build-Step Options 237 .addOption(javac) 238 .addOption(javaDoc) 239 .addOption(jdu) 240 .addOption(tarJar) 241 242 // Sync-Step Options 243 .addOption(syncJavaDoc) 244 .addOption(syncTarJar) 245 .addOption(syncLogs) 246 .addOption(setMaxAge) 247 248 // Composite-Step / Complete-Build Options 249 .addOption(buildRel) 250 .addOption(buildDevSMA) 251 .addOption(buildDev) 252 253 // Partial Debugging / Developer Build 254 .addOption(partialAll) 255 .addOption(partialSome) 256 257 // Run Links Checker 258 .addOption(linksCheck); 259 260 return group; 261 } 262 263 264 // ******************************************************************************************** 265 // ******************************************************************************************** 266 // Other / Extra Menu Options 267 // ******************************************************************************************** 268 // ******************************************************************************************** 269 270 271 // There are also three little "Extra Switches" that the user can provide / select. 272 // These three are just for convenience - making my life easier. 273 274 private static final String descriptionNQB = 275 "Prevent a Quick Build during Partial-Build's"; 276 277 private static final String descriptionJCP = 278 "Include the '.jar' File in the Class-Path"; 279 280 private static final String descriptionSRG = 281 "Skip the removal-step of all Java-Doc GCS Files, when synchronizing."; 282 283 private static final String descriptionTXL = 284 "Toggle whatever the default setting is for applying -Xlint:all"; 285 286 private static final String descriptionTXD = 287 "Toggle whatever the default setting is for applying -Xdiags:verbose"; 288 289 private static final String descriptionIEDP = 290 "Include Packages still Under Early Development in the Build"; 291 292 293 private static List<Option> otherNonGroupOptionNiceties() 294 { 295 final Option noQuickBuild = Option 296 .builder ("NQB") 297 .required (false) 298 .desc (descriptionNQB) 299 .longOpt ("noQuickBuild") 300 .hasArg (false) 301 .build(); 302 303 final Option putJarInCP = Option 304 .builder ("JCP") 305 .required (false) 306 .desc (descriptionJCP) 307 .longOpt ("putJarInCP") 308 .hasArg (false) 309 .build(); 310 311 final Option skipRemoveGCSFiles = Option 312 .builder ("SRG") 313 .required (false) 314 .desc (descriptionSRG) 315 .longOpt ("skipRemoveGCSFiles") 316 .hasArg (false) 317 .build(); 318 319 final Option overrideToggleXlintSwitch = Option 320 .builder ("TXL") 321 .required (false) 322 .desc (descriptionTXL) 323 .longOpt ("toggleDefaultXlint") 324 .hasArg (false) 325 .build(); 326 327 final Option overrideToggleXdiagsSwitch = Option 328 .builder ("TXD") 329 .required (false) 330 .desc (descriptionTXD) 331 .longOpt ("toggleDefaultXdiags") 332 .hasArg (false) 333 .build(); 334 335 final Option includeEarlyDevPkgsSwitch = Option 336 .builder ("IEDP") 337 .required (false) 338 .desc (descriptionIEDP) 339 .longOpt ("includeEarlyDev") 340 .hasArg (false) 341 .build(); 342 343 return List.of( 344 noQuickBuild, 345 putJarInCP, 346 skipRemoveGCSFiles, 347 overrideToggleXlintSwitch, 348 overrideToggleXdiagsSwitch, 349 includeEarlyDevPkgsSwitch 350 ); 351 } 352 353 354 // ******************************************************************************************** 355 // ******************************************************************************************** 356 // Process the Command-Line Arguments 357 // ******************************************************************************************** 358 // ******************************************************************************************** 359 360 361 CLI( 362 String GCS_DIR_DEV, 363 String GCS_DIR_RELEASE, 364 BuildPackage[] packageList, 365 String[] argv 366 ) 367 { 368 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 369 // Fill up Apache.CLI.Options (Get "Option" instances from the above two static methods) 370 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 371 372 final Options options = new Options(); 373 374 // The "OptionGroup" instance contains the complete list of Menu-Options offered by this 375 // Build Package. Exactly **ONE** of these Options should be selected by the user. 376 377 final OptionGroup optGroup = mainOptions(); 378 379 // Add the main / top-level Command-Line Arguments 380 options.addOptionGroup(optGroup); 381 382 // Add the little extras. 383 for (Option o : otherNonGroupOptionNiceties()) options.addOption(o); 384 385 386 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 387 // Parse 'argv' using 'options' - Do some error checking 388 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 389 390 final CommandLine commandLine; 391 392 try 393 { 394 commandLine = DefaultParser 395 .builder() 396 .setAllowPartialMatching(false) 397 .setStripLeadingAndTrailingQuotes(true) 398 .build() 399 .parse(options, argv, false /* stopAtNonOption */); 400 } 401 402 // This happens when the user hasn't provided at least one of the "OptionGroup" switches 403 // All of the "Option" instances inside the "OptionGroup" are the **COMPLETE** list of 404 // Menu-Options offered by this build. Exactly 1 must be provided at the command line, or 405 // else this exception throws. If so, just print an error message and exit. 406 407 catch (MissingOptionException moe) 408 { throw printMenuHelp(options, moe); } 409 410 // I haven't been through all of Apache's list of other possible error messages. If there 411 // is one, print the Help-Menu, and the exception's message and exit. 412 413 catch (ParseException pe) 414 { throw printMenuHelp(options, pe); } 415 416 417 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 418 // Retrieve the Selected-Option's name, instance-reference, & number-as-byte 419 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 420 421 final String selectedOptName = optGroup.getSelected(); 422 423 Option tempOpt = null; 424 for (Option o : optGroup.getOptions()) if (o.getOpt().equals(selectedOptName)) 425 { 426 tempOpt = o; 427 break; 428 } 429 430 // It just looks better / smarter when variables that aren't going to change are actuallly 431 // declared final 432 433 final Option selectedOpt = tempOpt; 434 435 // The argv-option parsing mechanism should already have thrown an exception if the user 436 // failed to choose any of the provided options. 437 438 if (selectedOpt == null) throw new UnreachableError(); 439 440 this.MENU_CHOICE = selectedOptName; 441 442 443 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 444 // More Error-Checking - This part can only be accomplished after filling in MENU_CHOICE 445 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 446 // 447 // There are only 2 menu-options that accept a list of package nick-names: 448 // 449 // "javac" (Option #1) Allows you to compile only the packages listed, if these names 450 // are included. 451 // 452 // "pb2" (Partion-Build #2) Also allows the option of only Syncing-To-GCS the packages 453 // listed 454 455 final boolean pkgNickNamesPossible = 456 this.MENU_CHOICE.equals("1") || this.MENU_CHOICE.equals("pb2"); 457 458 // I simply cannot get Apache.CLI to allow for an Option that accepts ZERO, ONE or MANY 459 // arguments. The possibilities with Apache.CLI seem to be either "ZERO or ONE" (an 460 // optional argument) **OR** "ONE-or-MORE" (multiple, but-not-zero). Therefore, I sort of 461 // have to rely on this "hack-y" thing where I check the "extra non-recognized" switches 462 // to allow for the case of ZERO, ONE or MANY arguments to Options "-1" and "-pb2" 463 464 final String[] extraneousArgs = commandLine.getArgs(); 465 466 // I can never tell (anywhere, when I'm coding!) if it is going to be null, or a 467 // zero-length-array. You eventually just get used to typing this... 468 // I'm also getting used to typing 'final' everywhere when I know a variable just 469 // isn't going to change. 470 471 final boolean EXTRA_PACKAGE_NICKNAMES = 472 ((extraneousArgs != null) && (extraneousArgs.length > 0)); 473 474 if (EXTRA_PACKAGE_NICKNAMES) 475 { 476 if (! pkgNickNamesPossible) throw printMenuHelp(options, extraneousArgs); 477 478 // These two lists, if non-empty, are going to cause an error-message to print, and the 479 // program exiting. 480 481 Stream.Builder<String> unrecognizedSwitchListB = Stream.builder(); 482 Stream.Builder<String> unrecognizedPackageListB = Stream.builder(); 483 484 TOP1: 485 for (String arg : extraneousArgs) 486 487 if (arg.startsWith("-")) unrecognizedSwitchListB.accept(arg); 488 489 else 490 { 491 for (BuildPackage bp : packageList) if (bp.nickName.equals(arg)) continue TOP1; 492 unrecognizedPackageListB.accept(arg); 493 } 494 495 // *** NEW-ADDITION: Check this list too - This "Extra For-Loop" is only here to ensure 496 // that the error message which is printed, includes all possible mistakes... 497 498 TOP2: 499 for (String arg : commandLine.getOptionValues(selectedOpt)) 500 { 501 for (BuildPackage bp : packageList) if (bp.nickName.equals(arg)) continue TOP2; 502 unrecognizedPackageListB.accept(arg); 503 } 504 505 // *** END-NEW-ADDITION: The "unrecognizedPackageListB" also includes the Package 506 // Nick-Names that Apache-CLI knows about... 507 508 final String[] unrecognizedSwitches = 509 unrecognizedSwitchListB.build().toArray(String[]::new); 510 511 final String[] unrecognizedPackages = 512 unrecognizedPackageListB.build().toArray(String[]::new); 513 514 // Print an error message and exit if either of these lists are non-empty 515 if ((unrecognizedSwitches.length + unrecognizedPackages.length) > 0) 516 throw printMenuHelp(options, unrecognizedSwitches, unrecognizedPackages); 517 } 518 519 520 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 521 // Fill in this class' "Extra Switch Fields" (These are the non-main-menu Switches) 522 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 523 // 524 // All of these variables are declared, even though they are largely just exact copies of 525 // the public fields declared at the top of this class - BECAUSE THOSE FIELDS ARE ALL 526 // DECLARED 'final' - Meaning they may only be assigned once in this giant constructor that 527 // I have written. 528 // 529 // Declaring them 'final' means they can also be declared 'public', and the end user can 530 // play with them to his heart's content, wihthout having the ability to screw anything up 531 // either! 532 533 boolean 534 NO_QUICK_BUILD_OPTION_SWITCH = false, 535 INCLUDE_JAR_IN_CP = false, 536 SKIP_REMOVE_GCS_FILES_OPTION_SWITCH = false, 537 OVERRIDE_TOGGLE_USE_XLINT_SWITCH = false, 538 OVERRIDE_TOGGLE_USE_XDIAGS_SWITCH = false, 539 EARLY_DEVELOPMENT_SWITCH = false; 540 541 // Get all processed / user-provided options 542 final Option[] optArr = commandLine.getOptions(); 543 544 for (Option opt : optArr) switch (opt.getOpt()) 545 { 546 case "NQB" : NO_QUICK_BUILD_OPTION_SWITCH = true; break; 547 case "JCP" : INCLUDE_JAR_IN_CP = true; break; 548 case "SRG" : SKIP_REMOVE_GCS_FILES_OPTION_SWITCH = true; break; 549 case "TXL" : OVERRIDE_TOGGLE_USE_XLINT_SWITCH = true; break; 550 case "TXD" : OVERRIDE_TOGGLE_USE_XDIAGS_SWITCH = true; break; 551 case "IEDP" : EARLY_DEVELOPMENT_SWITCH = true; break; 552 // default : continue; 553 } 554 555 this.INCLUDE_JAR_IN_CP = INCLUDE_JAR_IN_CP; 556 this.SKIP_REMOVE_GCS_FILES = SKIP_REMOVE_GCS_FILES_OPTION_SWITCH; 557 this.INCLUDE_EARLY_DEV_PACKAGES = EARLY_DEVELOPMENT_SWITCH; 558 559 // Only Main-Menu Option "Complete-Build-1" allows for writing to the "Release GCS Bucket" 560 this.toReleaseOrDeveloper = this.MENU_CHOICE.equals("cb1"); 561 562 // Only Main-Menu Option "#4 - TAR & JAR" accepts the "JARONLY" argument 563 final String optVal = commandLine.getOptionValue(selectedOpt); 564 this.JAR_ONLY = (optVal != null) && optVal.equals("JARONLY"); 565 566 this.QUICKER_BUILD = 567 (this.MENU_CHOICE.equals("cb1")) 568 || (this.MENU_CHOICE.equals("cb2")) 569 || (this.MENU_CHOICE.equals("cb3")) 570 ? false 571 : (! NO_QUICK_BUILD_OPTION_SWITCH); 572 573 this.GCS_DIR = this.toReleaseOrDeveloper 574 ? GCS_DIR_RELEASE 575 : GCS_DIR_DEV; 576 577 this.OVERRIDE_TOGGLE_USE_XLINT_SWITCH = OVERRIDE_TOGGLE_USE_XLINT_SWITCH; 578 this.OVERRIDE_TOGGLE_USE_XDIAGS_SWITCH = OVERRIDE_TOGGLE_USE_XDIAGS_SWITCH; 579 580 581 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 582 // More Error-Checking 583 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 584 // 585 // These simple error-checks are simply trying to inform the user when particular flags 586 // may or may not be applied. If, for instance, the user requested Main-Menu Option #4 587 // - Tar & Jar Files - then also providing the switch -SRG would simply be an error. The 588 // value of these error-checks is that, when they are more rigorous, the error/help 589 // explanations that are spit-out in their faces make explaining what any of this doing 590 // (at all), just that much easier to explain. 591 592 if (this.INCLUDE_JAR_IN_CP) 593 594 if (! MENU_CHOICE.equals("1")) throw printMenuHelp( 595 options, 596 "The " + BRED + "--putJarInCP" + RESET + " (-JCP) may only be used alongside " + 597 "Main-Menu Option " + BRED + "--javac" + RESET + " (-1)" 598 ); 599 600 // For -NQB, ONLY Main-Menu Options: -pb1 & -pb2, may receive this switch. 601 if (NO_QUICK_BUILD_OPTION_SWITCH) 602 603 if (StrCmpr.equalsNAND(MENU_CHOICE, "pb1", "pb2")) throw printMenuHelp( 604 options, 605 "The " + BRED + "--noQuickBuild" + RESET + " (-NQB) switch may only be applied " + 606 "to the Partial-Build Menu-Options " + BRED + "--partialAll" + RESET + " (-pb1) " + 607 "and " + BRED + "--partialSome" + RESET + " (-pb2)" 608 ); 609 610 // NOTE: Here, we need We DO NOT NEED TO TEST the value that was assigned to 611 // this.SKIP_REMOVE_GCS_FILES. We need to check the value indicating whether or not 612 // the user passed the switch on the Command-Line. 613 614 if (SKIP_REMOVE_GCS_FILES_OPTION_SWITCH) 615 616 if (StrCmpr.equalsNAND(MENU_CHOICE, "cb2", "cb3")) throw printMenuHelp( 617 options, 618 "The Command-Switch " + BRED + "--skipRemoveGCSFiles" + RESET + " (-SRG) may " + 619 "only be used in combination with Main-Menu Option " + BRED + "`--buildDevSMA`" + 620 RESET + " (-cb2) or " + BRED + "`--buildDev`" + RESET + " (-cb3)" 621 ); 622 623 if (this.OVERRIDE_TOGGLE_USE_XLINT_SWITCH || this.OVERRIDE_TOGGLE_USE_XDIAGS_SWITCH) 624 625 if (! MENU_CHOICE.equals("1")) throw printMenuHelp( 626 options, 627 "Switches " + BRED + "--toggleDefaultXlint" + RESET + " (-TXL) and " + BRED + 628 "--toggleDefaultXdiags" + RESET + " (-TXD) may only be used in combination with " + 629 "Main-Menu Option " + BRED + "`--javac`" + RESET + " (-1)" 630 ); 631 632 if (this.INCLUDE_EARLY_DEV_PACKAGES) 633 634 if (StrCmpr.equalsXOR(MENU_CHOICE, "4", "6", "7", "cb1")) throw printMenuHelp( 635 options, 636 "The Command-Switch " + BRED + "--includeEarlyDev" + RESET + " (-IEDP) may " + 637 "only be used in combination with some of the Main-Menu Options:\n" + 638 "-1, -2, -3, -5, -8, -cb2, -cb3, -pb1, -pb2" 639 ); 640 641 642 643 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 644 // Handle #1 & #21 - Package-NickNames / User-Specified Package-List 645 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 646 // 647 // If the Main-Menu Option is followed by a list of String-Tokens, the only possible 648 // presumption is that they are a list of package nick-names (or Option #4, the "JARONLY") 649 // String-Token Switch. 650 // 651 // Only Options #1 and #21 are allowed to accept the list of package nick-names 652 653 final String[] nickNames = commandLine.getOptionValues(selectedOpt); 654 final boolean nickNamesProvided = (nickNames != null) && (nickNames.length > 0); 655 656 // This error would (should !) automatically caught by Apache, and wouldnever reach this 657 // point. This is just a variant of 'assert', and it's staying here for now. 658 659 if (nickNamesProvided && (! pkgNickNamesPossible)) throw new UnreachableError(); 660 661 // A temporary list that is needed to merge the two different sources of Package Nick-Name 662 // arguments. Since I simply cannot get Apache's Option-Argument thing to work with a 663 // configuration of ZERO, ONE or MANY Option-Arguments, I have to presume that it isn't 664 // possible. As such, the source of Package Nick-Names are the "getOptionValues" **AND** 665 // **ALSO** the Extraneous-Options too! 666 // 667 // Merge those two lists, and then use that merged list as the package nick-names list. 668 // Remember that only options "1" (javac) and "pb2" (partial-build 2) even accept package 669 // nick-names lists. All of the others do not accept any arguments at all. 670 671 final ArrayList<String> l = new ArrayList<>(); 672 673 if (nickNamesProvided) 674 for (String pkgNickName : nickNames) l.add(pkgNickName); 675 676 if (EXTRA_PACKAGE_NICKNAMES) 677 for (String pkgNickName : extraneousArgs) l.add(pkgNickName); 678 679 this.userProvidedNickNames = nickNamesProvided 680 ? new ReadOnlyArrayList<String>(l) 681 : null; 682 683 this.userSpecifiedPackages = nickNamesProvided 684 ? BuildPackage.nickNameArgVPackages(packageList, this.userProvidedNickNames) 685 : null; 686 } 687 688 689 // ******************************************************************************************** 690 // ******************************************************************************************** 691 // Help-Menu Printing 692 // ******************************************************************************************** 693 // ******************************************************************************************** 694 695 696 // This happens when the Apache.CLI finds a Switch-Error 697 private UnreachableError printMenuHelp(Options options, ParseException pe) 698 { 699 printMenuHelp(options); 700 System.out.println(pe.getMessage()); 701 System.exit(1); 702 return null; // javac is too noisy 703 } 704 705 private UnreachableError printMenuHelp(Options options, String explanation) 706 { 707 printMenuHelp(options); 708 System.out.println(explanation); 709 System.exit(1); 710 return null; // javac is too noisy 711 } 712 713 // This Error-Message is printed/written when the user failed to provide at least one of the 714 // Main-Menu Switch-Options. 715 716 private UnreachableError printMenuHelp(Options options, MissingOptionException moe) 717 { 718 printMenuHelp(options); 719 720 System.out.println( 721 BRED + "You must select exactly one of the primary Build Options:\n\n" + RESET + 722 BYELLOW + " Build-Step Options:\n" + RESET + 723 " -1 <OPTIONAL-PKG-LIST> | -2 | -3 | -4 <JARONLY> | -5 | -6 | -7 | -8 |\n\n" + 724 BYELLOW + " Complete-Build Options:\n" + RESET + 725 " -cb1 | -cb2 | -cb3 |\n\n" + 726 BYELLOW + " Partial-Build Options:\n" + RESET + 727 " -pb1 | -pb2 <OPTIONAL-PKG-LIST> |\n\n" + 728 BYELLOW + " Links-Chcker Build:\n" + RESET + 729 " -LC\n\n" + 730 BCYAN + "Additional switches [-JCP, -NQB, -SRG, -TXD, -TXL, -IEDP], may also be added\n" + RESET 731 ); 732 733 System.exit(1); 734 return null; // javac is too noisy 735 } 736 737 private UnreachableError printMenuHelp(Options options, String[] unrecognizedSwitches) 738 { 739 printMenuHelp(options); 740 741 System.out.println( 742 "You have passed one or more spurious or unrecognized options:\n" + 743 BRED + "Unknown Command-Line Switches Include: " + RESET + 744 '[' + String.join(", ", unrecognizedSwitches) + ']' + '\n' 745 ); 746 747 System.exit(1); 748 return null; // javac is too noisy 749 } 750 751 private UnreachableError printMenuHelp 752 (Options options, String[] unrecognizedSwitches, String[] unrecognizedPackages) 753 { 754 printMenuHelp(options); 755 756 if (unrecognizedSwitches.length > 0) System.out.println( 757 "You have passed one or more spurious or unrecognized options:\n" + 758 BRED + "Unknown Command-Line Switches: " + RESET + 759 '[' + String.join(", ", unrecognizedSwitches) + ']' + '\n' 760 ); 761 762 if (unrecognizedPackages.length > 0) System.out.println( 763 "You have passed one or more unrecognized Package Nick-Names:\n" + 764 BRED + "Unknown Package Nick-Names: " + RESET + 765 '[' + String.join(", ", unrecognizedPackages) + ']' + '\n' 766 ); 767 768 System.exit(1); 769 return null; // javac is too noisy 770 } 771 772 // This is the "printMenuHelp" portion of the output-printer that is constant / consisten for 773 // all of the previous print-menu help-functions above. 774 775 private static String descriptionCommandLine = 776 "java MyBuildImpl -1 <PKG-LIST> | -2 | ... | -8 | -cb1 | -cb2 | -cb3 | -pb1 | " + 777 "-pb2 <PKG-LIST> | -LC\n" + 778 " [-JCP, -NQB, -SRG, -TXD, -TXL, -IEDP]"; 779 780 private static void printMenuHelp(Options options) 781 { 782 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 783 // Leave this here, I may try to bring this back one day, just not right now 784 // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** 785 786 System.out.println( 787 // BCYAN + "Old Build Menu:\n" + RESET + 788 HAND_TYPED_MAN_PAGE 789 // BCYAN + "\nApache Build Menu:\n" + RESET 790 ); 791 792 /* 793 HelpFormatter hf = new HelpFormatter(); 794 hf.setWidth(115); 795 hf.setLeftPadding(6); 796 hf.setOptionComparator(CLI::compareOptions); 797 */ 798 799 // Playing with these. They are a little silly. Leave this here, just to remember what 800 // Apache.CLI even does! 801 // 802 // hf.setLongOptPrefix("^"); 803 // hf.setLongOptSeparator("#"); 804 // hf.setOptPrefix("@"); 805 // hf.setSyntaxPrefix("!!"); 806 807 // hf.printHelp(descriptionCommandLine, options); 808 809 // System.out.println(); 810 } 811 812 // This long-winded thing is, apparently, the only way I could get Apache.CLI to order the 813 // Menu-Options using the "HelpFormatter" above. This is a java.util.Comparator 814 // Function-Pointer that actually "sorts" the Menu-Options for the Menu-Options-Printer method 815 // directly above. 816 // 817 // It sorts them to, sort of, emphasize, the Main-Menu Mandatory Options versus the 818 // Optional-Options. These "Optional-Options" are the little "Extra-Switches" listed at the 819 // very end of the Menu. 820 821 private static int compareOptions(Option o1, Option o2) 822 { 823 final String name1 = o1.getOpt(); 824 final String name2 = o2.getOpt(); 825 826 // The first 8 Build-Steps and 3 Complete-Build-Steps would automatically be properly 827 // sorted at the TOP OF THE LIST - using the Nature-Comparison-Order ANYWAY! There is no 828 // need to "subvert" the Natural-Sort-Order for Steps 1..8 and cb1, cb2 or cb3. They are 829 // already going to be sorted at the top of the list anyways, without any sort-order 830 // intervention. 831 832 final boolean naturalSort1 = (name1.length() == 1) || name1.startsWith("cb"); 833 final boolean naturalSort2 = (name2.length() == 1) || name2.startsWith("cb"); 834 835 if (naturalSort1 || naturalSort2) return name1.compareToIgnoreCase(name2); 836 837 // The two Partial-Build Main-Menu Options' Natural-Sort Order would innappropriately place 838 // them further down the Main-Menu than I would like them to be placed. Therefore, this 839 // comparator has to "intervene" and make sure they are next on the Comparitor's sort / 840 // return list - located DIRECTLY AFTER the three -cb (Complete-Build) Menu-Options. 841 842 final boolean pb1 = name1.startsWith("pb"); 843 final boolean pb2 = name2.startsWith("pb"); 844 845 if (pb1 && pb2) return name1.compareToIgnoreCase(name2); 846 847 if (pb1) return -1; 848 if (pb2) return 1; 849 850 // The last intervention is to place the "Links Check" Menu-Option DIRECTLY AFTER the 851 // "Partial-Build" (-pb1 & -pb2) Menu-Options. 852 853 final boolean lc1 = name1.startsWith("LC"); 854 final boolean lc2 = name2.startsWith("LC"); 855 856 if (lc1) return -1; 857 if (lc2) return 1; 858 859 // These are the "Extra-Switches" which add some features to make Life easier for me. 860 // These are placed at the VERY END of the menu, and their individual Menu-Placement / 861 // Sort-Order is completely irrelevant to me. So as long as these are at the end of the 862 // list, from that point, they may be placed in their Natural-Order Locations. 863 864 return name1.compareToIgnoreCase(name2); 865 } 866 867 static final String HAND_TYPED_MAN_PAGE = 868 BYELLOW + "\n\tJava Compiler Step:" + RESET + 869 "\n\t\t-1 -> Compile [Optional: Package-Nicknames)" + 870 871 BYELLOW + "\n\n\tBuild Steps:" + RESET + 872 "\n\t\t-2 -> JavaDoc" + 873 "\n\t\t-3 -> Upgrader" + 874 "\n\t\t-4 -> Build TAR's & JAR [Optional: 'JARONLY']" + 875 "\n\t\t-5 -> Copy to GCS: 'javadoc" + File.separator + "' directory" + 876 "\n\t\t-6 -> Copy to GCS: '.tar' and '.jar' files" + 877 "\n\t\t-7 -> Copy to GCS: logs" + 878 "\n\t\t-8 -> GSUTIL.SMA(GCS_DIR + \"**\", 150);" + 879 880 BYELLOW + "\n\n\tComplete Build (Composite Processes):" + RESET + 881 "\n\t\t-cb1 -> STEPS 2 through 7 [Pushes-To: GCP-Release]" + 882 "\n\t\t-cb2 -> STEPS 2 through 8 [Pushes-To: GCP-Developer] w/ Set-Max-Age " + 883 "\n\t\t-cb3 -> STEPS 2 through 7 [Pushes-To: GCP-Developer]" + 884 885 BYELLOW + "\n\n\tPartial-Debuging Build, (Push-To: GCP-Developer only):" + RESET + 886 "\n\t\t-pb1 -> SETPS 2 and 3 [Doc Only]" + 887 "\n\t\t-pb2 -> STEPS 2, 3, 5, and 8 [Doc, Sync & Max-Age. Optional: Package-Nicknames]" + 888 889 BYELLOW + "\n\n\tLinks-Checker:" + RESET + 890 "\n\t\t-LC -> STEPS 2 and 3, WITH-LINKS-CHECK" + 891 892 BYELLOW + "\n\n\tAdditional Side Options:" + RESET + 893 "\n\t\t-JCP,--putJarInCP " + descriptionNQB + 894 "\n\t\t-NQB,--noQuickBuild " + descriptionJCP + 895 "\n\t\t-SRG,--skipRemoveGCSFiles " + descriptionSRG + 896 "\n\t\t-TXD,--toggleDefaultXdiags " + descriptionTXD + 897 "\n\t\t-TXL,--toggleDefaultXlint " + descriptionTXL + 898 "\n\t\t-IEDP,--includeEarlyDev " + descriptionIEDP + 899 900 "\n"; 901}