001package Torello.JavaDoc;
002
003import Torello.Java.*;
004import Torello.HTML.*;
005
006import Torello.JavaDoc.Annotations.LinkJavaSource;
007
008import Torello.Java.Additional.RetN;
009
010import Torello.JDUInternal.MainJDU.ClassUpgradeData.*;
011
012import Torello.JDUInternal.Features.STATS.StatsInternal;
013
014import static Torello.Java.C.*;
015
016import Torello.JavaDoc.Messager.Messager;
017import Torello.JavaDoc.Messager.MsgVerbose;
018
019import Torello.JDUInternal.SimpleFeatures.LinksChecker;
020
021import Torello.JavaDoc.SyntaxHiLite.AbstractHashCodeHLC;
022import Torello.JavaDoc.SyntaxHiLite.HLC32;
023import Torello.JavaDoc.SyntaxHiLite.HLC64;
024import Torello.JavaDoc.SyntaxHiLite.HiLiteCache;
025
026import Torello.HTML.Tools.Images.IF;
027
028import Torello.Java.ReadOnly.ReadOnlyMap;
029import Torello.Java.ReadOnly.ReadOnlyList;
030import Torello.Java.ReadOnly.ReadOnlyArrayList;
031
032import Torello.Java.Build.BuildPackage;
033
034import java.util.*;
035import java.io.*;
036import java.util.stream.*;
037import java.util.function.*;
038
039
040/**
041 * The primary builder and configuration class for the Java Doc Upgrade Process, having many
042 * customizations that may be requested using the customize-settings methods available here.
043 * 
044 * <EMBED CLASS='external-html' DATA-FILE-ID=UPGRADE>
045 */
046public class Upgrade
047{
048    /**
049     * Initializes the Messager immediately, even before the {@link #upgrade()} method has begun
050     * running.  This can be useful if Java-Doc Upgrader Features are to be invoked before the 
051     * actual Upgrade Process begins.
052     * 
053     * @throws InternalError This throws if either the {@code 'verbosityLevel'} or the 
054     * {@code logFile} Upgrader Configurations have been altered or re-assigned previous to this
055     * method call.
056     */
057    public void initializeMessagerUsingCurAssignments()
058    {
059        Messager.initializeThreadLocalInstance
060            (settingsBuilder.verbosityLevel, settingsBuilder.logFile);
061    }
062
063
064    // ********************************************************************************************
065    // ********************************************************************************************
066    // Public-Static Constant/Final Fields
067    // ********************************************************************************************
068    // ********************************************************************************************
069
070
071    /** The name of the favicon-file (without extension).  This filename may not be changed. */
072    public static final String FAVICON_FILE_NAME = "favicon";
073
074    /** The name of the (very brief) {@code '.js'} file. */
075    public static final String JAVA_SCRIPT_FILE_NAME = "JDU.js";
076
077
078    // ********************************************************************************************
079    // ********************************************************************************************
080    // Private Fields (all are final/Constants - except "Stats")
081    // ********************************************************************************************
082    // ********************************************************************************************
083
084
085    // These are acctually for Internal-Use, and shouldn't be public.  Unfortunately due to Java's
086    // leaving out the 'friend' key-word from C/C++, these have to be public in order to share them
087    // with the Internal-Only Packages in JavaDoc-Upgrader.
088
089    private final UpgradePredicates.Builder  predicatesBuilder  = new UpgradePredicates.Builder();
090    private final UpgradeSettings.Builder    settingsBuilder    = new UpgradeSettings.Builder();
091    private final PathsAndTypes.Builder      pathsTypesBuilder  = new PathsAndTypes.Builder();
092
093    // Used by the log-file header string below
094    private final String dateTimeStr =
095        StrPrint.dateStr('-') + " " + StrPrint.timeStr(':');
096
097    // Prepended to the log-file that may (or may not) be saved to disk, or an Appendable
098    private final String logFileHeader = 
099        "<HTML>\n<HEAD>\n" +
100        "<TITLE>Log " + dateTimeStr + "</TITLE>\n" +
101        "<STYLE type='text/css'>\n" + C.getCSSDefinitions() + "\n</STYLE>\n" +
102        "</HEAD>\n" +
103        "<BODY STYLE='margin: 1em; background: black; color: white;'>\n\n" +
104        "<H1>JavaDoc Upgrader Log</H1>\n" +
105        "<CODE>" + dateTimeStr + "</CODE>\n" +
106        "<PRE>\n\n";
107
108    // used internally
109    private static final TextNode NEWLINE = new TextNode("\n");
110
111    // NOTE: This isn't final....  It will be constructed in this class....
112    private StatsInternal stats = null;
113
114
115    // ********************************************************************************************
116    // ********************************************************************************************
117    // Building / Constructor, Running the Upgrader
118    // ********************************************************************************************
119    // ********************************************************************************************
120
121
122    /**
123     * This returns a new instance of this class.  It will have all empty and null settings, except
124     * the root-directory descriptors.  It must be initialized with the various builder methods.
125     * 
126     * <BR /><BR />
127     * This constructor must tell the Upgrader (Builder) which directory contains {@code '.java'}
128     * Source-Files, and which directory shall contain Java-Doc Generated HTML Documentation Pages.
129     * 
130     * @param rootJavaDocDirectory This is the output directory that was used for the last call to
131     * the JavaDoc Utility.  The Upgrade Logic should expect to find all class, interface and
132     * enumerated types to be hilited in this directory.  This parameter may not be null.
133     * 
134     * @param rootSourceFileDirectories This is the location where the {@code '.java'} source files
135     * for the classes, interfaces and enumerated types named by your list files are stored.  This
136     * parameter may not be null; at least one directory must be passed.  If you have multiple
137     * source-code directories, then pass all of them, and whenever a JavaDoc {@code '.html'} file
138     * is loaded from disk, all source-code directories will be searched until the source-code is
139     * found.
140     * 
141     * @throws UpgradeException This exception will throw if either of these directories cannot be
142     * found, or may not be accessed.  The {@code 'getCause()'} method of the exception will
143     * provide more details of the specific error that occurred.
144     */
145    @LinkJavaSource(handle="MainConstructor")
146    public Upgrade(final String rootJavaDocDirectory, final String... rootSourceFileDirectories)
147    { 
148        final RetN r = MainConstructor.run(rootJavaDocDirectory, rootSourceFileDirectories);
149        this.pathsTypesBuilder.rootJavaDocDirectory         = r.GET(1);
150        this.pathsTypesBuilder.rootSourceFileDirectories    = r.GET(2);
151    }
152
153    /**
154     * <EMBED CLASS='external-html' DATA-FILE-ID=U_UPGRADE>
155     * 
156     * @return This returns the statistics computed for the upgrade process.  See class
157     * {@link Stats} for more information.  A complete listing of the information contained by
158     * the tables in a {@code 'Stats'} instance may be viewed by clicking the {@code 'Stats'}
159     * link at the top-right of this page.
160     * 
161     * <BR /><BR />If the Upgrade-Process had unrecoverable errors, null is returned.
162     */
163    public Stats upgrade()
164    {
165        Objects.requireNonNull(
166            this.settingsBuilder.hiLiter,
167            "Your HiLiter has not been configured.  You must either provide your own Customer " +
168            "HiLiter with a HiLiteCache Directory, otherwise this NullPointerException shall throw."
169        );
170
171        // This has to be initialized before the Embed-Tags can be checked for errors
172        Messager.initializeThreadLocalInstance
173            (settingsBuilder.verbosityLevel, settingsBuilder.logFile);
174
175        // Now Check the Global Embed-Tags Map for Errors
176        this.stats = GlobalEmbedTags.globalMapAndStats(this.settingsBuilder);
177
178        return Torello.JDUInternal.MainJDU.API_RUN.runTheUpgrader(
179            this.predicatesBuilder.build(),
180            this.settingsBuilder.build(),
181
182            // This class cannot be built, yet, one last thing to compute!
183            this.pathsTypesBuilder,
184
185            this.stats
186        );
187    }
188
189    /**
190     * <EMBED CLASS='external-html' DATA-FILE-ID=U_MAIN>
191     * @param argv This is the argument received from the command line.
192     */
193    public static void main(String[] argv) throws Exception
194    {
195        final Upgrade upgrader = new Upgrade(argv[0], "");
196
197        if (argv.length == 1) upgrader.upgrade();
198
199        else if (argv.length == 3) 
200        {
201            final File      f               = new java.io.File(argv[1]);
202            final boolean   _32_or_64_bit   = argv[2].equals("64");
203
204            final String hiLiterCacheDirectoryName;
205
206            if (! f.exists())
207            {
208                f.mkdirs();
209
210                hiLiterCacheDirectoryName =
211                    AbstractHashCodeHLC.initializeDirectory(argv[1], null);
212            }
213
214            else hiLiterCacheDirectoryName = argv[1];
215
216            final HiLiteCache CACHE = _32_or_64_bit
217                ? new HLC32(hiLiterCacheDirectoryName)
218                : new HLC64(hiLiterCacheDirectoryName);
219
220            upgrader.useHiLiterCache(CACHE).upgrade();
221            CACHE.persistMasterHashToDisk();
222        }
223
224        else System.out.println("Failed, expected one or three arguments");
225    }
226
227
228    // ********************************************************************************************
229    // ********************************************************************************************
230    // Filter-Predicates
231    // ********************************************************************************************
232    // ********************************************************************************************
233
234
235    /**  Write an explanation*/
236    @SuppressWarnings("unchecked")
237    public Upgrade setRemoveAllDetailsFilter(Predicate<? super String> cietCanonicalNameFilter)
238    {
239        this.predicatesBuilder.removeAllDetailsFilter =
240            (Predicate<String>) cietCanonicalNameFilter;
241        return this;
242    }
243
244    /**
245     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_REM_ALL_DET_F>
246     * @param entity Specifies which HTML Detail-Section to remove.
247     * @param cietCanonicalNameFilter <EMBED CLASS='external-html' DATA-FILE-ID=U_CCNF>
248     */
249    @LinkJavaSource(handle="SetEntityFilters", name="setRemoveAllDetailsFilter")
250    public Upgrade setRemoveAllDetailsFilter
251        (Entity entity, Predicate<? super String> cietCanonicalNameFilter)
252    {
253        SetEntityFilters.setRemoveAllDetailsFilter
254            (entity, cietCanonicalNameFilter, this.predicatesBuilder);
255        return this;
256    }
257
258    /**
259     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_HL_ALL_DET_F>
260     * @param cietCanonicalNameFilter <EMBED CLASS='external-html' DATA-FILE-ID=U_CCNF>
261     */
262    @LinkJavaSource(handle="SetEntityFilters", name="setHiLiteAllDetailsFilter")
263    public Upgrade setHiLiteAllDetailsFilter
264        (final Entity entity, final Predicate<? super String> cietCanonicalNameFilter)
265    {
266        SetEntityFilters.setHiLiteAllDetailsFilter
267            (entity, cietCanonicalNameFilter, this.predicatesBuilder);
268        return this;
269    }
270
271    /**
272     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_SUMM_REM_F>
273     * @param cietCanonicalNameFilter <EMBED CLASS='external-html' DATA-FILE-ID=U_CCNF>
274     */
275    @SuppressWarnings("unchecked")
276    public Upgrade setSummaryRemoveFilter(Predicate<? super String> cietCanonicalNameFilter)
277    {
278        this.predicatesBuilder.summaryRemoveFilter = (Predicate<String>) cietCanonicalNameFilter;
279        return this;
280    }
281
282    /**
283     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_HL_SCF_F>
284     * @param cietCanonicalNameFilter <EMBED CLASS='external-html' DATA-FILE-ID=U_CCNF>
285     */
286    @SuppressWarnings("unchecked")
287    public Upgrade setHiLiteSourceCodeFileFilter(Predicate<? super String> cietCanonicalNameFilter)
288    {
289        this.predicatesBuilder.hiLiteSourceCodeFileFilter =
290            (Predicate<String>) cietCanonicalNameFilter;
291
292        return this;
293    }
294
295    /**
296     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_CSS_TAGS_F>
297     * @param cietCanonicalNameFilter <EMBED CLASS='external-html' DATA-FILE-ID=U_CCNF>
298     */
299    @SuppressWarnings("unchecked")
300    public Upgrade setCSSTagsFilter(Predicate<? super String> cietCanonicalNameFilter)
301    {
302        this.predicatesBuilder.cssTagsFilter = (Predicate<String>) cietCanonicalNameFilter;
303        return this;
304    }
305
306    /**
307     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_VAL_HTML_F>
308     * @param cietCanonicalNameFilter <EMBED CLASS='external-html' DATA-FILE-ID=U_CCNF>
309     */
310    @SuppressWarnings("unchecked")
311    public Upgrade setValidateHTMLFilter(Predicate<? super String> cietCanonicalNameFilter)
312    {
313        this.predicatesBuilder.validateHTMLFilter = (Predicate<String>) cietCanonicalNameFilter;
314        return this;
315    }
316
317
318    // ********************************************************************************************
319    // ********************************************************************************************
320    // Setting Features: Output Printing and Log-File
321    // ********************************************************************************************
322    // ********************************************************************************************
323
324
325    /**
326     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_VERBOSITY_LVL>
327     * @param verbosity One of the four available {@link Verbosity} constants.
328     */
329    public Upgrade setVerbosityLevel(Verbosity verbosity)
330    {
331        this.settingsBuilder.verbosityLevel = verbosity.level;
332        if (verbosity.level == 3) MsgVerbose.setVerbose();
333        return this;
334    }
335
336    /**
337     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_LOG_FILE_APND>
338     * @param logFile An {@code Appendable} to be used for backing-up / saving Log-Writes.
339     */
340    public Upgrade setLogFile(Appendable logFile)
341    {
342        this.settingsBuilder.logFile = logFile;
343        return this;
344    }
345
346    /**
347     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_LOG_FILE_FN>
348     * @param logFileName File-Name of a writeable File, to be used for backuping-up Log-Writes
349     * @throws UpgradeException If the File provided cannot be written to.
350     * @see UpgradeException#checkFileIsWriteable(String, String, String)
351     */
352    @LinkJavaSource(handle="LogFile")
353    public Upgrade setLogFile(final String logFileName)
354    { LogFile.set(logFileName, this.settingsBuilder, this.logFileHeader); return this; }
355
356
357    // ********************************************************************************************
358    // ********************************************************************************************
359    // The HTML <EMBED> tag.  These can be used to provide more processing to the user.
360    // ********************************************************************************************
361    // ********************************************************************************************
362
363
364    /**
365     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_EMBED_TAG_F>
366     * @param tagIDMapFileName A Java {@code '.properties'} File-Name mapping File-ID's to Files.
367     * @throws UpgradeException If there are any problems that occur while loading the file
368     */
369    @LinkJavaSource(handle="GlobalEmbedTags", name="setMapFile")
370    public Upgrade setProjectGlobalEmbedTagsMapFile(final String tagIDMapFileName)
371    {
372        // this.stats = GlobalEmbedTags.setMapFile(tagIDMapFileName, this.settingsBuilder);
373        this.settingsBuilder.interimGlobalTagIDMapFileName = tagIDMapFileName;
374        return this;
375    }
376
377    /**
378     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_EMBED_TAG_MAP>
379     * @param tagIDMap This should map a {@code 'DATA-FILE-ID'} to an {@code '.html'} File-Name
380     */
381    @LinkJavaSource(handle="GlobalEmbedTags", name="setMap")
382    public Upgrade setProjectGlobalEmbedTagsMap(ReadOnlyMap<String, String> tagIDMap)
383    {
384        // this.stats = GlobalEmbedTags.setMap(tagIDMap, this.settingsBuilder);
385        this.settingsBuilder.projectGlobalEmbedTagsMap = tagIDMap;
386        return this;
387    }
388
389
390    // ********************************************************************************************
391    // ********************************************************************************************
392    // Using Features: The HiLiter & HiLiter-Cache
393    // ********************************************************************************************
394    // ********************************************************************************************
395
396
397    /**
398     * Convenience Method.
399     * <BR />Invokes: {@link HiLiter#getDefault(HiLiteCache)}
400     * <BR />And-Then: {@link #setHiLiter(HiLiter)}
401     */
402    public Upgrade useHiLiterCache(HiLiteCache cache)
403    {
404        Objects.requireNonNull(cache, "HiLiteCache 'cache' Parameter has been passed null.");
405        setHiLiter(HiLiter.getDefault(cache));
406        this.settingsBuilder.hlCache = cache;
407        return this;
408    }
409
410    /**
411     * Configures the HiLiter to use the Default HiLiter, and use the provided Cache-Directory as
412     * the location for Caching HiLited HTML-Files.
413     * 
414     * @param hiLiterCacheDirectoryName The name of the File-System Directory which has 
415     * previously saved HiLited HTML-Files.
416     * 
417     * <BR /><BR /><DIV CLASS=JDHint>
418     * <B STYLE='color: red;'>Note:</B> If this is the first time using this Cache
419     * Directory, and it doesn't exists yet, this directory will be created, and future
420     * {@code Upgrade} instances will save &amp; cache HiLited-Source HTML to this directory.
421     * </DIV>
422     */
423    public Upgrade useHiLiterCache(String hiLiterCacheDirectoryName, boolean _32_or_64_bit)
424    {
425        Objects.requireNonNull(
426            hiLiterCacheDirectoryName,
427            "HiLiteCache 'hiLiterCacheDirectoryName' Parameter has been passed null."
428        );
429
430
431        // These four lines allow the Upgrade Tool to cache results for documentation web-pages
432        // as they are hilited so that future builds will not have to "re-poll" the CLI when
433        // hiliting source-code files that have not changed.
434
435        final File f = new File(hiLiterCacheDirectoryName);
436    
437        if (! f.exists())
438        {
439            f.mkdirs();
440
441            // Creates the directory if it doesn't exist
442            hiLiterCacheDirectoryName =
443                AbstractHashCodeHLC.initializeDirectory(hiLiterCacheDirectoryName, null);
444        }
445
446        final HiLiteCache cache = _32_or_64_bit
447            ? new HLC32(hiLiterCacheDirectoryName)
448            : new HLC64(hiLiterCacheDirectoryName);
449
450        setHiLiter(HiLiter.getDefault(cache));
451        this.settingsBuilder.hlCache = cache;
452        return this;
453    }
454
455    /**
456     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_HILITER>
457     * @param hiLiter Any valid implementation of the {@link HiLiter} interface
458     */
459    public Upgrade setHiLiter(HiLiter hiLiter)
460    {
461        this.settingsBuilder.hiLiter = hiLiter;
462        return this;
463    }
464
465    /**
466     * Retrieve the currently assigned {@link HiLiter} instance.
467     * @return The most recently assigned {@link HiLiter} instance.
468     */
469    public HiLiter getCurrentHiLiter() { return this.settingsBuilder.hiLiter; }
470
471
472    // ********************************************************************************************
473    // ********************************************************************************************
474    // The Big Kahuna Burger.  That is a tasty burger.  Brad - did I break your concentration?
475    // ********************************************************************************************
476    // ********************************************************************************************
477
478
479    /**
480     * <EMBED CLASS='external-html' DATA-FILE-ID=U_GET_DEF_CSS_FILES>
481     * @return All Java-Doc Upgrader {@code '.css'} Files
482     * @see #setCustomCSSFiles(CSSFiles)
483     */
484    public static CSSFiles retrieveDefaultCSSFilesFromJAR()
485    {
486        return LFEC.readObjectFromFile_JAR
487            (Upgrade.class, "data-files/AllCSSFiles.objdat", true, CSSFiles.class);
488    }
489
490    /**
491     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_CSS_FILES>
492     * @param cssFiles All Java-Doc Upgrader {@code '.css'} Files
493     * @see #retrieveDefaultCSSFilesFromJAR()
494     */
495    public Upgrade setCustomCSSFiles(CSSFiles cssFiles)
496    {
497        this.settingsBuilder.cssFiles = cssFiles;
498        return this;
499    }
500
501    /**
502     * <EMBED CLASS='external-html' DATA-FILE-ID=U_GET_DEF_JS_FILE>
503     * @return The <B STYLE='color:red'><I>entire contents</I></B> of the {@code '.js'} File (read
504     * from disk), returned as a {@code String}.
505     */
506    public static String retrieveDefaultJSFileFromJAR()
507    {
508        return LFEC.readObjectFromFile_JAR
509            (Upgrade.class, "data-files/JDU-JS.sdat", true, String.class);
510    }
511
512    /**
513     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_FAVICON_IF>
514     * @param faviconFileFormat An instance of {@link IF} - the Image-Format of the Favicon-File.
515     */
516    public Upgrade setFaviconFileFormat(IF faviconFileFormat)
517    {
518        this.settingsBuilder.faviconImageFileName =
519            FAVICON_FILE_NAME + '.' + faviconFileFormat.toString();
520
521        return this;
522    }
523
524    /**
525     * Retrieve the File-Name of the Favicon, if one has been assigned.
526     * @return The currently assigned favicon file-name, or null if a favicon was not assigned
527     */
528    public String getFaviconImageFileName()
529    { return this.settingsBuilder.faviconImageFileName; }
530
531
532    /**
533     * <EMBED CLASS='external-html' DATA-FILE-ID=U_ADD_HEADER_TAGS>
534     * @param headerTags HTML-Tags to be inserted into a page's {@code <HEAD>...</HEAD>} Section
535     */
536    public Upgrade addHeaderTags(Iterable<TagNode> headerTags)
537    {
538        Vector<HTMLNode> ht = this.settingsBuilder.headerTags;
539        for (TagNode tn : headerTags) { ht.add(tn); ht.add(NEWLINE); }
540        return this;
541    }
542
543    /**
544     * <EMBED CLASS='external-html' DATA-FILE-ID=U_ADD_HEADER_BLOCK>
545     * @param headerStuff HTML-Block to be inserted into a page's {@code <HEAD>...</HEAD>} Section
546     */
547    public Upgrade addHeaderBlock(Vector<HTMLNode> headerStuff)
548    { this.settingsBuilder.headerTags.addAll(headerStuff);  return this; }
549
550    /** <EMBED CLASS='external-html' DATA-FILE-ID=U_RUN_LINKS_CHECKER> */
551    public Upgrade runLinksChecker()
552    {
553        this.settingsBuilder.linksChecker = new LinksChecker();
554        return this;
555    }
556
557    /**
558     * Sets a tab-replacement policy for code-hilited HTML.
559     * 
560     * @param spacesPerTab The number of spaces that should be used as a substitue for a
561     * tab-character ({@code '\t'}) when hiliting source-code.
562     * 
563     * @param relativeOrAbsolute When this parameter receives {@code TRUE}, a tab-character is
564     * used to symbolize however many spaces are needed to place the cursor at the next 
565     * <B STYLE='color: red;'>rounded-integral</B> number-of-spaces - modulo the value in
566     * {@code 'spacesPerTab'}.
567     * 
568     * <BR /><BR />If a tab-charcter is found at index {@code 13} in a line-of-code, and the value
569     * passed to {@code 'spacesPerTab'} were {@code 4}, then the number of spaces inserted would be
570     * {@code 3}.  This is because precisely {@code 3} spaces would skip to index {@code 16}, which
571     * happens to be the next-highest <B STYLE='color: red;'>rounded-multiple</B> of {@code 4}. 
572     * 
573     * <BR /><BR />When this parameter receives {@code FALSE}, a tab-character is always 
574     * replaced by the exact number of space-characters specified by {@code spacesPerTab}.
575     * 
576     * @throws IllegalArgumentException If a number less than {@code 1} or greater than {@code 20}
577     * is passed to parameter {@code 'spacesPerTab'} 
578     * 
579     * @see StrIndent#setCodeIndent_WithTabsPolicyRelative(String, int, int)
580     * @see StrIndent#setCodeIndent_WithTabsPolicyAbsolute(String, int, String)
581     */
582    @LinkJavaSource(handle="TabsPolicy")
583    public Upgrade setTabsPolicy(int spacesPerTab, boolean relativeOrAbsolute)
584    { TabsPolicy.set(spacesPerTab, relativeOrAbsolute, this.settingsBuilder); return this; }
585
586    /**
587     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_CHECK_BALANCE>
588     * @param checkBalance The value of this parameter can turn the balance checker on or off.
589     */
590    public Upgrade setCheckBalance(boolean checkBalance)
591    {
592        this.settingsBuilder.checkBalance = checkBalance;
593        return this;
594    }
595
596    /**
597     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_EXTRA_TASKS>
598     * 
599     * @param extraTasks This function-pointer may be used to, sort-of, do extra processing on a
600     * JavaDoc HTML Documentation File while the vectorized-html file is already loaded into
601     * memory - and parsed.
602     * 
603     * <BR /><BR />The class {@link JavaDocHTMLFile} provides many accessor methods to retrieve
604     * the Summary Tables, and the HTML Details - <I>along with reflection-classes about the
605     * {@link Method}'s, {@link Field}'s, etc... that they describe</I>
606     */
607    public Upgrade setExtraTasks(Consumer<JavaDocHTMLFile> extraTasks)
608    {
609        this.settingsBuilder.extraTasks = extraTasks;
610        return this;
611    }
612
613    /**
614     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_PKGSUMM_CLEAN>
615     * @param packageSummaryCleaner Java Lambda for modifying Vectorized-HTML.
616     */
617    public Upgrade setPackageSummaryCleaner(Consumer<Vector<HTMLNode>> packageSummaryCleaner)
618    {
619        this.settingsBuilder.packageSummaryCleaner = packageSummaryCleaner;
620        return this;
621    }
622
623    /** <EMBED CLASS='external-html' DATA-FILE-ID=U_USE_DEFAULT_PSC> */
624    public Upgrade useDefaultPackageSummaryCleaner()
625    {
626        this.settingsBuilder.packageSummaryCleaner = PackageSummaryHTML::defaultCleaner;
627        return this;
628    }
629
630    /**
631     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_PKG_LIST_BP>
632     * @param packageList Instances of {@link Torello.Java.Build}'s class {@link BuildPackage}.
633     * @return {@code 'this'} instance, for method-invocation chaining.
634     * @see #setPackageList(String[])
635     */
636    public Upgrade setPackageList(Iterable<BuildPackage> packageList)
637    {
638        TreeSet<String> ts = new TreeSet<>();
639        for (BuildPackage bp : packageList) ts.add(bp.fullName);
640        this.predicatesBuilder.packagesToUpgradeFilter = StrFilter.strListKEEP(ts, false)::test;
641        return this;
642    }
643
644    /**
645     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_PKG_LIST_STR>
646     * @param packageList A list of Package-Name's as a {@code String}.
647     * @return {@code 'this'} instance, for method-invocation chaining.
648     * @see #setPackageList(Iterable)
649     */
650    public Upgrade setPackageList(String... packageList)
651    {
652        this.predicatesBuilder.packagesToUpgradeFilter =
653            StrFilter.strListKEEP(false, packageList)::test;
654
655        return this;
656    }
657
658    /**
659     * A Configuration-Setting for requesting that the Upgrader Auto-Generate the original Java
660     * {@code 'package-frame.html'} &amp; {@code 'overview-frame.html'} Files.
661     * 
662     * <EMBED CLASS='external-html' DATA-FILE-ID=U_SET_GEN_FRAMES>
663     * 
664     * @param generateFrames The {@code boolean}-Setting for this Configuration-Field
665     * @return {@code 'this'} instance, for method-invocation chaining.
666     * 
667     * @throws UpgradeException If {@code 'generateFrames'} is passed {@code FALSE}, but you have
668     * earlier configured / applied an {@code 'overview-frame.html'} sorter.
669     * 
670     * @see PackageSummaryHTML#JD_FRAMES_WARNING_MESSAGE
671     */
672    public Upgrade setGenerateFrames(boolean generateFrames)
673    {
674        this.settingsBuilder.generateFrames = generateFrames;
675
676        if ((! generateFrames) && (this.settingsBuilder.overviewFrameSections != null))
677
678            throw new UpgradeException(
679                "Generate-Frames cannot be turned off if an Overview-Frame Sorter has already " +
680                "been applied"
681            );
682
683        return this;
684    }    
685
686    /**
687     * Generate and sort an {@code 'overview-frame.html'} File.
688     * @param sectionNames List of "Categories" or "Sections" for the packages
689     * @param sectionContents List of Packages for each Category / Section.
690     * @return {@code 'this'} instance, for method-invocation chaining.
691     */
692    @LinkJavaSource(handle="OverviewFrameSorter")
693    public Upgrade setOverviewFrameSorter(String[] sectionNames, String[][] sectionContents)
694    { OverviewFrameSorter.set(sectionNames, sectionContents, this.settingsBuilder); return this; }
695
696
697    // This is only used to prevent the "Overview Frame Sorter" from causing a Messager
698    // Exception-Throw when the Build has Opted for a "Quick-Build" - and the Overview
699    // Frame Sorter hasn't removed the Quick-Build Packages from its sort!
700    // 
701    // Later this will also be used for the (upcoming - soon) "UNDER_DEVELOPMENT" BuildPackage 
702    // flag.
703    // 
704    // This is an Internal-Method that is largely completely useless for the end user.  Hence it is
705    // Package-Visible (available through the "EXPORT_PORTAL")
706
707    void registerEliminatedBuildPackages(ReadOnlyList<BuildPackage> eliminatedBuildPackages)
708    { this.settingsBuilder.eliminatedBuildPackages = eliminatedBuildPackages; }
709
710}