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