1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
package Torello.Java.Build;

import Torello.JavaDoc.Upgrade;

import Torello.Java.Verbosity;
import Torello.Java.StrCmpr;
import Torello.Java.EmptyListException;
import Torello.Java.WritableDirectoryException;

import Torello.Java.ReadOnly.ROArrayListBuilder;

import Torello.HTML.Tools.Images.IF;

import static Torello.Java.C.BYELLOW;
import static Torello.Java.C.BCYAN;
import static Torello.Java.C.RESET;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Objects;
import java.util.regex.Pattern;

import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * This class provides a list of fields, all of which may be modified and configured, for providing
 * any needed settings to class {@link BuilderRecord}.
 * 
 * <BR /><BR />Use the {@code public} constructor offered by this class, and then set and change
 * the values of any of the Configuration-Fields.  Once this class Configuration-Fields have been
 * appropriately set to contain your project's data, pass the instance to the {@link BuilderRecord}
 * class' only constructor (along with an argv {@code String[]}-Array).
 * 
 * <BR /><BR />This will inform the {@code BuilderRecord}-Constructor of all of your nedded
 * settings, and once built, will make running your project's build script very easy.
 */
public final class Config
{
    // ********************************************************************************************
    // ********************************************************************************************
    // Validator Constants
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * Project-Name validation {@code String}.  The value passed to configuration field/parameter
     * must match this regular expression.  This is used in this class {@link #validate()} method.
     * 
     * @see #PROJECT_NAME
     * @see BuilderRecord#PROJECT_NAME
     * @see #validate()
     */
    public static final Predicate<String> projectNameValidator =
        Pattern.compile("^\\w[\\w\\d]*$").asPredicate();


    // ********************************************************************************************
    // ********************************************************************************************
    // Configuration Instance Fields
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * To-Do, Explain This
     * @see BuilderRecord#HOME_DIR
     */
    public String HOME_DIR = null;

    /**
     * The File-System Directory-Location where Java-Doc Output is sent for storage.  Also the 
     * directory that the Upgrader searches to retrieve and parse JavaDoc Files.
     *  
     * @see BuilderRecord#LOCAL_JAVADOC_DIR
     */
    public String LOCAL_JAVADOC_DIR = "javadoc" + java.io.File.separator;

    /**
     * A simple name for this Project.  Name must pass the {@link #projectNameValidator}
     * Regular-Expression.
     * 
     * @see BuilderRecord#PROJECT_NAME
     * @see #projectNameValidator
     */
    public String PROJECT_NAME = null;

    /**
     * The Major Version Number of the Current Build.  This class {@link #validate()} method checks
     * to ensure that this field contains a positive integer / byte value.
     * 
     * @see BuilderRecord#VERSION_MAJOR_NUMBER
     */
    public byte VERSION_MAJOR_NUMBER = 1;

    /**
     * The Minor Version Number of the Current Build.  This class {@link #validate()} method checks
     * to ensure that this field contains a positive integer / byte value.
     * 
     * @see BuilderRecord#VERSION_MINOR_NUMBER
     */
    public byte VERSION_MINOR_NUMBER = 0;

    /**
     * The full or partial Path-Name of the {@code 'javac'} binary to use for compiling this
     * project.  This parameter / field may not be null, or a {@code NullPointerException} will
     * throw.
     * 
     * <BR /><BR /><B CLASS=JDDescLabel>Default Setting:</B>
     * 
     * <BR />The default setting for this Configuration-Field is just the command name, which
     * is to presume that the {@code PATH} environment-variable has been set to facilitate finding
     * {@code 'javac'}
     * 
     * @see BuilderRecord#JAVAC_BIN
     */
    public String JAVAC_BIN = "javac";

    /**
     * The full or partial Path-Name of the {@code 'javac'} binary to use for compiling this
     * project.  This parameter / field may not be null, or a {@code NullPointerException} will
     * throw.
     * 
     * <BR /><BR /><B CLASS=JDDescLabel>Default Setting:</B>
     * 
     * <BR />The default setting for this Configuration-Field is just the command name, which
     * is to presume that the {@code PATH} environment-variable has been set to facilitate finding
     * {@code 'javadoc'}.
     * 
     * @see BuilderRecord#JAVADOC_BIN
     */
    public String JAVADOC_BIN = "javadoc";

    /**
     * The number to provide to the {@code --release} switch to {@code javac}.  This number may be
     * set to any negative value, and it will prevent the {@code BuilderRecord} from using this
     * switch at all.
     * 
     * @see BuilderRecord#JAVA_RELEASE_NUM_SWITCH
     */
    public byte JAVA_RELEASE_NUM_SWITCH = -1;

    /**
     * Currently unused, but originally used to indicate the {@code javadoc} version being used
     * @see BuilderRecord#JAVADOC_VER
     */
    public byte JAVADOC_VER = 11;

    /**
     * If the <B>Stage 3</B> {@link Upgrade}-Process utilizes a favicon on its Web-Pages, then this
     * field may be assigned to the location on disk where that favicon is located.
     * 
     * <BR /><BR />When this field contains a non-null Image-File, that image will be copied (after
     * upgrade has completed) directly to the {@code 'javadoc'} output directory.  When this field
     * is left null, it will be ignored and no favicon image is copied.
     * 
     * @see BuilderRecord#FAVICON
     */
    public String FAVICON = null;

    /**
     * Source-Directory to be used as root directory for archiving
     * @see BuilderRecord#TAR_SOURCE_DIR
     */
    public String TAR_SOURCE_DIR = null;

    /**
     * This optional configuration field is optional, and may be used to move / relocate the
     * {@code '.jar'} File after it's built by this Build-Processor.  If there is a diretory or
     * location on the File-System into which the {@code '.jar'} should be moved, then provide that
     * directory's name here.
     * 
     * <BR /><BR />When this field is left null, it will be silently ignored; furthermore, the
     * {@code '.jar'} File which the Build-Processor creates will be left in the Current Working
     * Directory.
     */
    public String JAR_FILE_MOVE_DIR = null;

    /**
     * The directory location where log information will be saved.  This configuration field may
     * not be null, or a {@code NullPointerException} will throw.
     */
    public String LOG_DIR = null;

    /**
     * The <B>Stage 3</B> {@link Upgrade} instance to invoke.  This parameter-field configuration
     * may not be null, or a {@code NullPointerException} will throw.
     */
    public Upgrade upgrader = null;

    /**
     * The script invoked <B STYLE='color: red'><I>before</I></B> the <B>Stage 3</B> call to
     * {@link Upgrade}.  This configuration may be assigned null, and in such cases, no script will
     * be invoked before the upgrader runs.
     * 
     * @see BuilderRecord#preUpgraderScript
     */
    public UpgradeProcessor preUpgraderScript = null;

    /**
     * The script invoked <B STYLE='color: red'><I>after</I></B> the <B>Stage 3</B> call to
     * {@link Upgrade}.  This configuration may be assigned null, and in such cases, no script will
     * be invoked before the upgrader runs.
     * 
     * @see BuilderRecord#postUpgraderScript
     */
    public UpgradeProcessor postUpgraderScript = null;

    /**
     * For Stage 1, the Java-Compiler Stage, this Configuration-Field may be assigned any
     * switch-{@code String's}, and they will be passed to the {@code javac} invocation.
     * 
     * <BR /><BR />This field's value may be left null, or assigned a zero-length 
     * {@code String[]}-Array and, in both cases, it shall be ignored.
     * 
     * @see BuilderRecord#extraSwitchesJAVAC
     */
    public String[] extraSwitchesJAVAC = null;

    /**
     * For Stage 2, the {@code javadoc} Stage, this Configuration-Field may be assigned any
     * switch-{@code String's}, and they will be passed to the {@code javadoc} invocation.
     * 
     * <BR /><BR />This field's value may be left or null, or assigned a zero-length 
     * {@code String[]}-Array, and, in both cases, it shall be ignored.
     * 
     * @see BuilderRecord#extraSwitchesJAVADOC
     */
    public String[] extraSwitchesJAVADOC = null;

    /**
     * The list of Java Packages to compile.  This list may be neither empty nor null, or an
     * exception will throw.
     * 
     * @see BuilderRecord#packageList
     */
    public BuildPackage[] packageList = null;

    /**
     * The Root Class-File Directories to use with {@code 'javac'}.  This is used to generate the
     * value passed to the {@code -cp} switch passed when <B>Stage 1</B> invokes the Java-Compiler.
     * This parameter / field may be empty or null, and if it is, it will be ignored.
     */
    public String[] CLASS_PATH = null;

    /**
     * This allows for specifying a list of files to manually add into the {@code '.jar'} that is
     * built by this package.
     * 
     * <BR /><BR /><B CLASS=JDDescLabel>Constructor Call:</B>
     * 
     * <BR />Because it isn't necessary to include any "Extra Files" into the {@code '.jar'}, there
     * is some likelihood that this Configuration-Field wouldn't ever be needed / used.  Make sure
     * to call the {@link JarInclude} constructor, first, to build an instance of this Config-Field
     * before attempting to use it.  Notice that it is initially initialized to null!
     * 
     * <BR /><BR /><B CLASS=JDDescLabel>Common Usess:</B>
     * 
     * <BR />Java-HTML has quite a few Data-Files that are inserted into the Jar-File, manually,
     * using this class.  There may also be the need to insert {@code META-INF/} directory files
     * that name things like Annotation-Processor locations, taglets, or other Java Services.
     * 
     * @see BuilderRecord#jarIncludes
     */
    public JarInclude jarIncludes = null;

    /**
     * Requests that when {@code 'javac'} is invoked, the switch {@code -Xlint:all,-processing} is
     * included in the command-line invocation.
     * 
     * @see BuilderRecord#USE_XLINT_SWITCH
     */
    public boolean USE_XLINT_SWITCH = true;

    /**
     * Requests that when {@code 'javac'} is invoked, the switch {@code -Xdiags:verbose} is
     * included in the command-line invocation.
     * 
     * @see BuilderRecord#USE_XDIAGS_SWITCH
     */
    public boolean USE_XDIAGS_SWITCH = true;

    /**
     * JavaDoc Frames were a true majesty that should never have been eliminated.  If you would
     * prefer to remove them, or you are using JDK 21+ which no longer accepts the {@code --frames}
     * switch, then set this Configuration-Field to {@code FALSE}.
     * 
     * @see BuilderRecord#NO_JAVADOC_FRAMES_SWITCH
     */
    public boolean NO_JAVADOC_FRAMES_SWITCH = false;


    // ********************************************************************************************
    // ********************************************************************************************
    // Cloud Synchronization
    // ********************************************************************************************
    // ********************************************************************************************


    @SuppressWarnings("rawtypes")
    final ROArrayListBuilder<CloudSync> cloudSyncListBuilder = new ROArrayListBuilder<>();

    public void addCloudSync(CloudSync cloudSync)
    {
        Objects.requireNonNull(cloudSync, "You have passed null to parameter 'cloduSync'");
        this.cloudSyncListBuilder.add(cloudSync);
    }


    // ********************************************************************************************
    // ********************************************************************************************
    // Constructor
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * Creates an instance of this class, with all default values assigned to the parameter /
     * fields.
     * 
     * <BR /><BR />The intention is that an instance of this class will have its
     * Configuration-Fields property assigned, according to the needs of the Project being built.
     * Afterwards, the {@code 'Config'} instance may be passed to the Package-Private
     * {@code 'BuilderRecord'}-Constructor using this class' {@link #createBuilder(String[])}
     * method.
     * 
     * <BR /><BR />Performing a build is done using {@link RunBuild#run(BuilderRecord)}.
     * 
     * @see #createBuilder(String[])
     * @see RunBuild#run(BuilderRecord)
     */
    public Config() { }


    // ********************************************************************************************
    // ********************************************************************************************
    // Methods: createBuilder & validate
    // ********************************************************************************************
    // ********************************************************************************************


    /**
     * Used by class {@link BuilderRecord} to validate all user-provided data on a best efforts
     * basis.
     * 
     * @throws NullPointerException If any of the configuration parameter/fields listed here have
     * been assigned null
     * 
     * <BR /><UL CLASS=JDUL>
     * <LI>{@link #LOCAL_JAVADOC_DIR}</LI>
     * <LI>{@link #PROJECT_NAME}</LI>
     * <LI>{@link #JAVAC_BIN}</LI>
     * <LI>{@link #JAVADOC_BIN}</LI>
     * <LI>{@link #TAR_SOURCE_DIR}</LI>
     * <LI>{@link #LOG_DIR}</LI>
     * <LI>{@link #upgrader}</LI>
     * <LI>{@link #packageList}</LI>
     * </UL>
     * 
     * <BR />This exception will also be thrown if these lists contain any null-valued
     * entries:
     * <BR /><UL CLASS=JDUL>
     * <LI>{@link #packageList}</LI>
     * <LI>{@link #CLASS_PATH}</LI>
     * </UL>
     * 
     * @throws IllegalArgumentException If any of these configuration fields were assigned a 
     * negative number:
     * <BR /><UL CLASS=JDUL>
     * <LI>{@link VERSION_MAJOR_NUMBER}</LI>
     * <LI>{@link VERSION_MINOR_NUMBER}</LI>
     * <LI>{@link JAVADOC_VER}</LI>
     * </UL>
     * 
     * <BR />This exception will also be thrown if:
     * <BR /><UL CLASS=JDUL>
     * <LI> {@link #PROJECT_NAME} does not pass the {@link #projectNameValidator} test.</LI>
     * </UL>
     * 
     * @throws FileNotFoundException This exception will throw if either of these fields are not
     * assigned a valid File-System Directory-Name:
     * <BR /><UL CLASS=JDUL>
     * <LI> {@link #FAVICON}</LI>
     * <LI> {@link #TAR_SOURCE_DIR}</LI>
     * </UL>
     * 
     * @throws UnrecognizedImageExtException If the {@link #FAVICON} Image-Format cannot be 
     * properly "guessed" by class {@link IF}.
     * 
     * @throws EmptyListException If {@link #packageList} has been assigned an empty list.
     * 
     * @throws WriteableDirectoryException If parameter {@link #JAR_FILE_MOVE_DIR} is assigned a 
     * non-null value, but the {@code String} assigned it does not point to a File-System
     * directory, or that directory is not writeable.
     * 
     * <BR /><BR />Also throws if {@link #LOG_DIR} is not a valid directory-name, that allows
     * write-access.
     */
    public final void validate() throws java.io.FileNotFoundException
    {
        Objects.requireNonNull(LOCAL_JAVADOC_DIR,   M1 + "LOCAL_JAVADOC_DIR" + M2);
        Objects.requireNonNull(PROJECT_NAME,        M1 + "PROJECT_NAME" + M2);
        Objects.requireNonNull(JAVAC_BIN,           M1 + "JAVAC_BIN" + M2);
        Objects.requireNonNull(JAVADOC_BIN,         M1 + "JAVADOC_BIN" + M2);
        Objects.requireNonNull(TAR_SOURCE_DIR,      M1 + "TAR_SOURCE_DIR" + M2);
        Objects.requireNonNull(LOG_DIR,             M1 + "LOG_DIR" + M2);
        Objects.requireNonNull(upgrader,            M1 + "upgrader" + M2);
        Objects.requireNonNull(packageList,         M1 + "packageList" + M2);

        if (! projectNameValidator.test(PROJECT_NAME)) throw new IllegalArgumentException
            (M1 + "PROJECT_NAME] was not passed a valid name.");

        if (VERSION_MAJOR_NUMBER < 0) throw new IllegalArgumentException
            (M1 + "VERSION_MAJOR_NUMBER" + M3 + VERSION_MAJOR_NUMBER);

        if (VERSION_MINOR_NUMBER < 0) throw new IllegalArgumentException
            (M1 + "VERSION_MINOR_NUMBER" + M3 + VERSION_MINOR_NUMBER);

        if (JAVADOC_VER < 0) throw new IllegalArgumentException
            (M1 + "JAVADOC_VER" + M3 + JAVADOC_VER);

        if (FAVICON != null)
        {
            File f = new File(FAVICON);

            if ((! f.exists()) || (! f.isFile())) throw new FileNotFoundException(
                "Field 'FAVICON' [" + FAVICON + "] points to a file that was not found, or " +
                "isn't a File"
            );

            IF.guessOrThrow(FAVICON);
        }

        if (packageList.length == 0) throw new EmptyListException
            (M1 + "packageList] was passed a list of size 0.");

        for (BuildPackage bp : packageList) if (bp == null) throw new NullPointerException
            (M1 + "packageList] contains a null value.");

        for (String p : CLASS_PATH) if (p == null) throw new NullPointerException
            (M1 + "CLASS_PATH] contains a null value.");

        File f = new File(TAR_SOURCE_DIR);
        if (! (f.exists() && f.isDirectory())) throw new FileNotFoundException
            (M1 + "] was not passed a vaild File-System Directory-Name.");

        if (JAR_FILE_MOVE_DIR != null)
        {
            WritableDirectoryException.check(JAR_FILE_MOVE_DIR);

            if (! JAR_FILE_MOVE_DIR.endsWith(File.separator))
                JAR_FILE_MOVE_DIR = JAR_FILE_MOVE_DIR + File.separator;
        }

        WritableDirectoryException.check(LOG_DIR);

        if (! LOG_DIR.endsWith(File.separator)) LOG_DIR = LOG_DIR + File.separator;
    }

    private static final String M1 = "The Parameter-Field Configuration [";
    private static final String M2 = "] was ultimately assigned null.";
    private static final String M3 = "] was passed a negative number: ";

    final String classPathStr(boolean INCLUDE_JAR_IN_CP, String JAR_FILE_NAME)
    {
        if (CLASS_PATH == null) return INCLUDE_JAR_IN_CP ? JAR_FILE_NAME : null;

        final String sep = StrCmpr.containsIgnoreCase(System.getProperty("os.name"), "win")
            ? ";"
            : ":";

        final StringBuilder sb  = new StringBuilder();

        for (int i=0; i < CLASS_PATH.length; i++) sb.append(((i==0) ? "" : sep) + CLASS_PATH[i]);

        if (INCLUDE_JAR_IN_CP) sb.append(sep + JAR_FILE_NAME);

        return sb.toString();
    }


    /**
     * Processes Command-Line Inputs, and creates an instance of {@link BuilderRecord}.
     * You may initiate a build using that class by calling the {@link RunBuild#run(BuilderRecord)}
     * method.
     * 
     * @param argv The Command-Line Inputs
     * 
     * @return An instance of {@link BuilderRecord}.  You may invoke the method
     * {@link RunBuild#run(BuilderRecord)} to initiate a build.
     * 
     * @throws FileNotFoundException Throw by the class {@link Config}
     * {@link Config#validate() validate} method if there are problems with the user's provided
     * configurations.
     * 
     * @throws IOException Thrown if there are IO Problems while reading any of the files in the
     * Class-Path, or other configurations.
     */
    public BuilderRecord createBuilder(String[] argv) throws FileNotFoundException, IOException
    { return new BuilderRecord(this, argv); }


    // ********************************************************************************************
    // ********************************************************************************************
    // java.lang.Object
    // ********************************************************************************************
    // ********************************************************************************************


    public String toString()
    {
        final Config DEF = new Config();

        // public String            HOME_DIR                    = null;
        // public String            LOCAL_JAVADOC_DIR = "javadoc" + java.io.File.separator;
        // public String            PROJECT_NAME                = null;
        // public byte              VERSION_MAJOR_NUMBER        = 1;
        // public byte              VERSION_MINOR_NUMBER        = 0;
        // public String            JAVAC_BIN                   = "javac";
        // public String            JAVADOC_BIN                 = "javadoc";
        // public byte              JAVA_RELEASE_NUM_SWITCH     = -1;
        // public byte              JAVADOC_VER                 = 11;
        // public String            FAVICON                     = null;
        // public String            TAR_SOURCE_DIR              = null;
        // public String            JAR_FILE_MOVE_DIR           = null;
        // public String            LOG_DIR                     = null;
        // public Upgrade           upgrader                    = null;
        // public UpgradeProcessor  preUpgraderScript           = null;
        // public UpgradeProcessor  postUpgraderScript          = null;
        // public String[]          extraSwitchesJAVAC          = null;
        // public String[]          extraSwitchesJAVADOC        = null;
        // public BuildPackage[]    packageList                 = null;
        // public String[]          CLASS_PATH                  = null;
        // public JarInclude        jarIncludes                 = null;
        // public boolean           USE_XLINT_SWITCH            = true;
        // public boolean           USE_XDIAGS_SWITCH           = true;
        // public boolean           NO_JAVADOC_FRAMES_SWITCH    = false;

        return 

            // public String HOME_DIR
            BCYAN + "HOME_DIR:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + " **** " + /*this.HOME_DIR*/ "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.HOME_DIR + "\n\n" +

            // public String LOCAL_JAVADOC_DIR
            BCYAN + "LOCAL_JAVADOC_DIR:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.LOCAL_JAVADOC_DIR + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.LOCAL_JAVADOC_DIR + "\n\n" +

            // public String PROJECT_NAME
            BCYAN + "PROJECT_NAME:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.PROJECT_NAME + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.PROJECT_NAME + "\n\n" +

            // public byte VERSION_MAJOR_NUMBER
            BCYAN + "VERSION_MAJOR_NUMBER:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.VERSION_MAJOR_NUMBER + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.VERSION_MAJOR_NUMBER + "\n\n" +

            // public byte VERSION_MINOR_NUMBER
            BCYAN + "VERSION_MINOR_NUMBER:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.VERSION_MINOR_NUMBER + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.VERSION_MINOR_NUMBER + "\n\n" +

            // public String JAVAC_BIN
            BCYAN + "JAVAC_BIN:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.JAVAC_BIN + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.JAVAC_BIN + "\n\n" +

            // public String JAVADOC_BIN
            BCYAN + "JAVADOC_BIN:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.JAVADOC_BIN + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.JAVADOC_BIN + "\n\n" +

            // public byte JAVA_RELEASE_NUM_SWITCH
            BCYAN + "JAVA_RELEASE_NUM_SWITCH:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.JAVA_RELEASE_NUM_SWITCH + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.JAVA_RELEASE_NUM_SWITCH + "\n\n" +

            // public byte JAVADOC_VER
            BCYAN + "JAVADOC_VER:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.JAVADOC_VER + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.JAVADOC_VER + "\n\n" +

            // public String FAVICON
            BCYAN + "FAVICON:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.FAVICON + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.FAVICON + "\n\n" +

            // public String TAR_SOURCE_DIR
            BCYAN + "TAR_SOURCE_DIR:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.TAR_SOURCE_DIR + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.TAR_SOURCE_DIR + "\n\n" +

            // public String JAR_FILE_MOVE_DIR
            BCYAN + "JAR_FILE_MOVE_DIR:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.JAR_FILE_MOVE_DIR + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.JAR_FILE_MOVE_DIR + "\n\n" +

            // public String LOG_DIR
            BCYAN + "LOG_DIR:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.LOG_DIR + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.LOG_DIR + "\n\n" +

            // public Upgrader upgrader
            BCYAN + "upgrader:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.upgrader + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.upgrader + "\n\n" +

            // public UpgradeProcessor preUpgraderScript
            BCYAN + "preUpgraderScript:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.preUpgraderScript + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.preUpgraderScript + "\n\n" +

            // public UpgradeProcessor postUpgraderScript
            BCYAN + "postUpgraderScript:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.postUpgraderScript + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.postUpgraderScript + "\n\n" +

            // public String[] extraSwitchesJAVAC
            BCYAN + "extraSwitchesJAVAC:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + SARR(this.extraSwitchesJAVAC) + "\n\t" +
                BYELLOW + "Default: " + RESET + SARR(DEF.extraSwitchesJAVAC) + "\n\n" +

            // public String[] extraSwitchesJAVADOC
            BCYAN + "extraSwitchesJAVADOC:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + SARR(this.extraSwitchesJAVADOC) + "\n\t" +
                BYELLOW + "Default: " + RESET + SARR(DEF.extraSwitchesJAVADOC) + "\n\n" +

            // public BuildPackage[] packageList
            BCYAN + "packageList:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + PLARR(this.packageList) + "\n\t" +
                BYELLOW + "Default: " + RESET + PLARR(DEF.packageList) + "\n\n" +

            // public String[] CLASS_PATH
            BCYAN + "CLASS_PATH:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + SARR(this.CLASS_PATH) + "\n\t" +
                BYELLOW + "Default: " + RESET + SARR(DEF.CLASS_PATH) + "\n\n" +


            // public JarInclude jarIncludes
            BCYAN + "jarIncludes:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.jarIncludes + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.jarIncludes + "\n\n" +

            // public boolean USE_XLINT_SWITCH
            BCYAN + "USE_XLINT_SWITCH:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.USE_XLINT_SWITCH + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.USE_XLINT_SWITCH + "\n\n" +

            // public boolean USE_XDIAGS_SWITCH
            BCYAN + "USE_XDIAGS_SWITCH:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.USE_XDIAGS_SWITCH + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.USE_XDIAGS_SWITCH + "\n\n" +

            // public boolean NO_JAVADOC_FRAMES_SWITCH
            BCYAN + "NO_JAVADOC_FRAMES_SWITCH:\n\t" + RESET + 
                BYELLOW + "Value:   " + RESET + this.NO_JAVADOC_FRAMES_SWITCH + "\n\t" +
                BYELLOW + "Default: " + RESET + DEF.NO_JAVADOC_FRAMES_SWITCH + "\n\n";
    }

    private static String SARR(String[] sArr)
    {
        if (sArr == null) return "[null]";
        StringBuilder sb = new StringBuilder();
        for (String s : sArr) sb.append("\n\t\t" + s);
        return sb.toString();
    }

    private static String PLARR(BuildPackage[] packageList)
    {
        if (packageList == null) return "[null]";
        StringBuilder sb = new StringBuilder();
        for (BuildPackage bp : packageList) sb.append("\n\t\t" + bp.fullName);
        return sb.toString();
    }
}