001package Torello.Java.Build;
002
003import Torello.Java.ReadOnly.ReadOnlyList;
004import Torello.Java.ReadOnly.ReadOnlyArrayList;
005
006import Torello.Java.StringParse;
007import Torello.Java.StrCSV;
008
009import Torello.Java.Additional.Ret2;
010
011import java.util.function.Predicate;
012import java.io.IOException;
013
014/**
015 * This class will accept the User-Provided list of Packages that may be built during a build,
016 * and generate a final list of packages that will be processed during any given build - <I>as
017 * initiated at the command line by user command</I>.
018 * 
019 * <BR /><BR />Is a utility used internally by the following Build-Stages:
020 *
021 * <BR /><BR /><UL CLASS=JDUL>
022 * <LI>Class {@link BuilderRecord} Constructor</LI>
023 * <LI>Compilation / Stage-1</LI>
024 * <LI>Documentation / Java-Doc / Stage-2</LI>
025 * </UL>
026 * 
027 * <BR />
028 * <EMBED CLASS='external-html' DATA-FILE-ID=INTERNAL_CLASS_NOTE>
029 */
030@Torello.JavaDoc.StaticFunctional
031public class Packages
032{
033    private Packages() { }
034
035    /**
036     * Used in the Class {@link BuilderRecord}-Constructor to specify, exactly, which packages may
037     * or may not be processed during an invocation of the {@link RunBuild#run(BuilderRecord)}
038     * method.
039     * 
040     * @param cli The Object that represents / contains the switches and User-Requests that were
041     * obtained at the Command-Line from the Command-Line Parser Object {@link CLI}.
042     * 
043     * @param usersBuildPackageList The list of {@link BuildPackage} instances that were passed to
044     * the User-Configuration Class {@link Config}.  The reference passed to this parameter is the
045     * exact same reference that is found in {@link Config#packageList}.
046     * 
047     * @return This, essentially, returns the exact same input list, but after it has been divided
048     * into two sets - those packages that are going to be included in the Build, and any packages
049     * that are not part of the build.
050     * 
051     * <BR /><BR />The packages that are 'removed' from the build are:
052     * 
053     * <BR /><BR /><UL CLASS=JDUL>
054     *
055     * <LI> <B>{@link BuildPackage#EARLY_DEVELOPMENT Early-Development} Packages</B>
056     *      <BR />These are packages which are not completed yet, and are not ready for
057     *      publication &amp; distribution.
058     *      <BR /><BR /></LI>
059     *
060     * <LI> <B>{@link BuildPackage#QUICKER_BUILD_SKIP Skip-On-Quick-Build} Packages</B>
061     *      <BR />These are packages which are aren't necessarily imperative for the
062     *      proper functioning of JAR, and for speed and a faster development time can be
063     *      eliminated from your {@code '.jar'} when focusing on other parts of the build.
064     *      </LI>
065     *
066     * </UL>
067     * 
068     * <BR /><BR /><B CLASS=JDDescLabel>Inclusion Decisions:</B>
069     * 
070     * <BR />The decision that remove packages from the list of "Packages to Process
071     * in the Build" can be reversed at the Command-Line using the {@code '-NQB'} (No Quick Build)
072     * or the {@code '-IEDP'} (Include Early-Development Packages.)
073     * 
074     * <BR /><BR />Utlimately this method returns two lists, contained by an instance of
075     * {@link Ret2}.  The instances of {@link BuildPackage} that are going to be processed during
076     * a build are in one list, and the {@code BuildPackage} instances to be skipped are in the
077     * second list.
078     * 
079     * <BR /><BR /><UL CLASS=JDUL>
080     * 
081     * <LI> <B>{@code Ret2.a: ReadOnlyList<BuildPackage>}</B>
082     *      <BR />The list of packages to be processed in this build.
083     *      <BR /><BR /></LI>
084     * 
085     * <LI> <B>{@code Ret2.b: ReadOnlyList<BuildPackage>}</B>
086     *      <BR />The list of packages to that are being skipped in this build.
087     *      </LI>
088     * 
089     * </UL>
090     */
091    static Ret2
092        <
093            ReadOnlyList<BuildPackage>,
094            ReadOnlyList<BuildPackage>
095        >
096        packagesInThisBuild
097        (final CLI cli, final BuildPackage[] usersBuildPackageList)
098    {
099        // This is a little complicated.  All this is doing is "merging" a suite of User-Provided
100        // configurations from about three different places.
101        // 
102        // The class "BuildPackage" allows the user to configure settings for the packages.  One of
103        // those settings allows a user to assert that a package is a "Skip if Quick Build."  In my
104        // world all that is talking about is the "Torello.Browser" Package, which:
105        //
106        //      1) Takes for ever to compile
107        //      2) Takes even longer to run the Java-Doc (and even longer for the upgrader)
108        //      3) MOST-IMPORTANTLY: Never changes at all, because i'm not working on it right now.
109        //         As a result, pretending it doesn't exist, except when compiling with a -cb
110        //         "Complete Build" (The actual "Release Directory"), makes working a lot easier
111        //
112        // Class CLI also allows users to configure stuff by passing switches.  It's mechanisms
113        // involve arguments passed to the "String[] argv" parameter via the
114        // "public static void main" method. 
115        // 
116        // Class 'Config' allows a user to provide configurations too, and the user's choice for a
117        // CloudSync list does, indeed, affect one minor part of this method, the name of the main
118        // menu option switch for Composite-Step Buid's for Steps #1 to #4 (a specific/particular 
119        // choice that's provided at the Main-Menu).  When this one is selected, it is possible for
120        // a Partial-Build to actually require the Quick-Build stuff to be included, rather than 
121        // being eliminated!
122        // 
123        // The field CLI.QUICKER_BUILD is a boolean that's computed inside the class CLI
124        // Constructor.  If you go look at it, it's kind of simple.  Any time a user has selected a
125        // "Complete-Build" Menu-Option at the Command-Line, the field CLI.QUICKER_BUILD is
126        // guaranteed to be FALSE.
127        // 
128        // If the User has selected a "Partial-Build", the CLI Field "QUICKER_BUILD" is guaranteed
129        // to be TRUE (since that's the whole point of a Package which was assigned "Skip on Quick
130        // Build" ==> Specifically Partial-Build's are "Developer-Builds", where the programmer is
131        // currently focusing on something totally different, and doesn't want his Command-Line
132        // Build to waste a bunch of time on a giant-package which is completely irrelevant and
133        // hasn't changed at all in months).
134        // 
135        // NOTE, on the off-chance that the user selected a Partial-Build that performs, precisely,
136        // steps #1 to #4, then the CLI-Field "QUICKER_BUILD" will also be assigned false.  This is
137        // becasue Step-4 / Stage-4 is the Archive "Tar & Jar" step, and packages CAN NEVER BE
138        // ELIMINATED FROM THE ARCHIVE FILES.  (Their documentation pages are skipped when copying
139        // their '.html' Files to the Web-Site, which can speed up a build be at least a minute).
140        // 
141        // A minute is a lot of time when you are running this stuff over and over and over.
142        //
143        // In Java-HTML, as of March 2024, the CSS Tokenizer (which is going to have extremely
144        // limited use, since "parsing CSS" is several orders of magnitude less useful than parsing
145        // HTML) - ... the "CSS Tokenizer" is an "Early Development" package.  Early Development
146        // packages have almost the same behavior, they are left out completely (just like the
147        // Quick-Build packages) - except when they are explicity requested.
148        // 
149        // ========================================================================================
150        // NOTE: "QUICK_BUILD" and "EARLY_DEVELOPMENT" packages are treated as if they just don't
151        //       exist, unless the user has made specific requests for them at the command line CLI
152        // ========================================================================================
153        // 
154        // If a package isn't going to be processed during the build, it is placed into Ret2.b
155
156        final boolean IS_FULL_COMPILE = (cli.sor.userSpecifiedPackages == null);
157
158        final Predicate<BuildPackage> FILT = (BuildPackage bp) ->
159        {
160            if (cli.QUICKER_BUILD) if (bp.skipIfQuickerBuild)
161
162                return IS_FULL_COMPILE
163                    ? false
164                    : cli.sor.userSpecifiedPackages.contains(bp);
165
166            if (bp.earlyDevelopment)
167            {
168                if (cli.aor.INCLUDE_EARLY_DEV_PACKAGES_SWITCH) return true;
169
170                return IS_FULL_COMPILE
171                    ? false
172                    : cli.sor.userSpecifiedPackages.contains(bp);
173            }
174
175            return true;
176        };
177
178        final ReadOnlyArrayList<BuildPackage> packagesIncluded =
179            new ReadOnlyArrayList<BuildPackage>(FILT, usersBuildPackageList);
180
181        final ReadOnlyArrayList<BuildPackage> packagesEliminated = 
182            new ReadOnlyArrayList<BuildPackage>(FILT.negate(), usersBuildPackageList);
183
184        return new Ret2<>(packagesIncluded, packagesEliminated);
185    }
186
187    /**
188     * This determines which packages should be re-compiled in the Stage 1 Build-Class
189     * {@link S01_JavaCompiler}.
190     * 
191     * @param brec This instance contains all information obtained from the User via the
192     * User-Settings class {@link Config}, and information obtained via the Command-Line
193     * Interface {@link CLI}.
194     * 
195     * @return The list of packages whose files are to be recompiled, based on the User-Settings
196     * provided class {@link Config}, and the User-Request that were made at the {@link CLI}, 
197     * Command-Line Interface
198     */
199    static ReadOnlyList<BuildPackage> packagesToCompile(final BuilderRecord brec)
200        throws IOException
201    {
202        // It is important to "get" the BuildPackage Configuration-Flags.  
203        //
204        // The value of BuildPackge.mustReCompile is defined in (surprise) class BuildPackage, as
205        // follows, here:
206        //
207        // this.earlyDevelopment   = (flags & EARLY_DEVELOPMENT) >= 1;
208        // this.skipIfQuickerBuild = (flags & QUICKER_BUILD_SKIP)  >= 1;
209        // 
210        // this.mustReCompile =
211        //         (! this.earlyDevelopment)
212        //     &&  (! this.skipIfQuickerBuild)
213        //     &&  ((flags & DO_NOT_RECOMPILE) == 0); // == 0 implies the "NOT" of the flag
214        //
215        // FINALLY: The cli.userSpecifiedPackages is literally just the Package-NickNames tht are
216        //          provided to class CLI via the "public static void main" method that gets it.
217
218        final boolean IS_FULL_COMPILE = (brec.cli.sor.userSpecifiedPackages == null);
219
220        final Predicate<BuildPackage> FILT = (brec.cli.aor.INCLUDE_EARLY_DEV_PACKAGES_SWITCH)
221            ? (BuildPackage bp) -> bp.mustReCompile || bp.earlyDevelopment
222            : (BuildPackage bp) -> bp.mustReCompile;
223
224        final ReadOnlyList<BuildPackage> packagesToCompile = IS_FULL_COMPILE
225            ? new ReadOnlyArrayList<>(brec.packageList, FILT, brec.packageList.size())
226            : brec.cli.sor.userSpecifiedPackages;
227
228        return packagesToCompile;
229    }
230
231    /**
232     * This determines which packages should be run through {@code 'javadoc'}, in the Stage 2
233     * Build-Class {@link S02_JavaDoc}.
234     * 
235     * @param brec This instance contains all information obtained from the User via the
236     * User-Settings class {@link Config}, and information obtained via the Command-Line
237     * Interface {@link CLI}.
238     * 
239     * @return The list of packages whose files are to be sent to the {@code javadoc} Tool, based
240     * on the User-Settings provided class {@link Config}, and the User-Request that were made at
241     * the {@link CLI}, Command-Line Interface.
242     */
243    static ReadOnlyList<BuildPackage> packagesToJavaDoc(final BuilderRecord brec)
244    {
245        // Copied from the class `BuildPackage
246        //
247        // this.mustDocument        = (flags & DO_NOT_DOCUMENT)     == 0; // The "NOT" of the flag
248        // this.earlyDevelopment    = (flags & EARLY_DEVELOPMENT)   >= 1;
249        // this.skipIfQuickerBuild  = (flags & QUICKER_BUILD_SKIP)  >= 1;
250
251        final Predicate<BuildPackage> FILT = (BuildPackage pkg) -> pkg.mustDocument;
252
253        final ReadOnlyList<BuildPackage> ret = new ReadOnlyArrayList<>
254            (brec.packageList, FILT, brec.packageList.size());
255
256        return ret;
257    }
258}