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 * Decide which User-Provided Packages will be put through the various Build-Stages.
016 */
017@Torello.JavaDoc.StaticFunctional
018public class Packages
019{
020    private Packages() { }
021
022    /**
023     * Used in the Class {@link Builder}-Constructor to specify, exactly, which packages may or may
024     * not be processed during an invocation of that class' {@link Builder#build() build} method.
025     * 
026     * @param cli The Object that represents / contains the switches and User-Requests that were
027     * obtained at the Command-Line from the Command-Line Parser Object {@link CLI}.
028     * 
029     * @param usersBuildPackageList The list of {@link BuildPackage} instances that were passed to
030     * the User-Configuration Class {@link Config}.  The reference passed to this parameter is the
031     * exact same reference that is found in {@link Config#packageList}.
032     * 
033     * @return This, essentially, returns the exact same input list, but after it has been divided
034     * into two sets - those packages that are going to be included in the Build, and any packages
035     * that are not part of the build.
036     * 
037     * <BR /><BR />The packages that are 'removed' from the build are:
038     * 
039     * <BR /><BR /><UL CLASS=JDUL>
040     *
041     * <LI> <B>{@link BuildPackage#EARLY_DEVELOPMENT Early-Development} Packages</B>
042     *      <BR />These are packages which are not completed yet, and are not ready for
043     *      publication &amp; distribution.
044     *      <BR /><BR /></LI>
045     *
046     * <LI> <B>{@link BuildPackage#QUICKER_BUILD_SKIP Skip-On-Quick-Build} Packages</B>
047     *      <BR />These are packages which are aren't necessarily imperative for the
048     *      proper functioning of JAR, and for speed and a faster development time can be
049     *      eliminated from your {@code '.jar'} when focusing on other parts of the build.
050     *      </LI>
051     *
052     * </UL>
053     * 
054     * <BR /><BR /><B CLASS=JDDescLabel>Inclusion Decisions:</B>
055     * 
056     * <BR />The decision that remove packages from the list of "Packages to Process
057     * in the Build" can be reversed at the Command-Line using the {@code '-NQB'} (No Quick Build)
058     * or the {@code '-IEDP'} (Include Early-Development Packages.)
059     * 
060     * <BR /><BR />Utlimately this method returns two lists, contained by an instance of
061     * {@link Ret2}.  The instances of {@link BuildPackage} that are going to be processed during
062     * by {@link Builder} are in one list, and the {@code BuildPackage} instances to be skipped are
063     * in the second list.
064     * 
065     * <BR /><BR /><UL CLASS=JDUL>
066     * 
067     * <LI> <B>{@code Ret2.a: ReadOnlyList<BuildPackage>}</B>
068     *      <BR />The list of packages to be processed in this build.
069     *      <BR /><BR /></LI>
070     * 
071     * <LI> <B>{@code Ret2.b: ReadOnlyList<BuildPackage>}</B>
072     *      <BR />The list of packages to that are being skipped in this build.
073     *      </LI>
074     * 
075     * </UL>
076     */
077    public static Ret2
078        <
079            ReadOnlyList<BuildPackage>,
080            ReadOnlyList<BuildPackage>
081        >
082        packagesInThisBuild
083        (CLI cli, BuildPackage[] usersBuildPackageList)
084    {
085        // This is a little complicated.  All this is doing is "merging" a suite of User-Provided
086        // configurations from about three different places.
087        // 
088        // The class "BuildPackage" allows the user to configure settings for the packages.  One of
089        // those settings allows a user to assert that a package is a "Skip if Quick Build."  In my
090        // world all that is talking about is the "Torello.Browser" Package, which:
091        //
092        //      1) Takes for ever to compile
093        //      2) Takes even longer to run the Java-Doc (and even longer for the upgrader)
094        //      3) MOST-IMPORTANTLY: Never changes at all, because i'm not working on it right now.
095        //         As a result, pretending it doesn't exist, except when compiling with -cb1
096        //         "Complete Build 1" (The actual "Release Directory"), makes working a lot easier
097        //
098        // Class CLI also allows users to configure stuff by passing switches.  It's mechanisms
099        // involve arguments passed to the "String[] argv" parameter via the
100        // "public static void main" method.
101        //
102        // In Java-HTML, as of March 2024, the CSS Tokenizer (which is going to have extremely
103        // limited use, since "parsing CSS" is several orders of magnitude less useful than parsing
104        // HTML) - ... the "CSS Tokenizer" is an "Early Development" package.  Early Development
105        // packages have almost the same behavior, they are left out completely (just like the
106        // Quick-Build packages) - except when they are explicity requested.
107        //
108        // ========================================================================================
109        // NOTE: "QUICK_BUILD" and "EARLY_DEVELOPMENT" packages are treated as if they just don't
110        //       exist, unless the user has made specific requests for them at the command line CLI
111        // ========================================================================================
112        //
113        // If a package isn't going to be processed during the build, it is placed into Ret2.b
114
115        final boolean IS_FULL_COMPILE = (cli.userSpecifiedPackages == null);
116
117        final Predicate<BuildPackage> FILT = (BuildPackage bp) ->
118        {
119            if (cli.QUICKER_BUILD) if (bp.skipIfQuickerBuild)
120
121                return IS_FULL_COMPILE
122                    ? false
123                    : cli.userSpecifiedPackages.contains(bp);
124
125            if (bp.earlyDevelopment)
126            {
127                if (cli.INCLUDE_EARLY_DEV_PACKAGES) return true;
128
129                return IS_FULL_COMPILE
130                    ? false
131                    : cli.userSpecifiedPackages.contains(bp);
132            }
133
134            return true;
135        };
136
137        final ReadOnlyArrayList<BuildPackage> packagesIncluded =
138            new ReadOnlyArrayList<BuildPackage>(FILT, usersBuildPackageList);
139
140        final ReadOnlyArrayList<BuildPackage> packagesEliminated = 
141            new ReadOnlyArrayList<BuildPackage>(FILT.negate(), usersBuildPackageList);
142
143        return new Ret2<>(packagesIncluded, packagesEliminated);
144    }
145
146    /**
147     * This determines which packages should be re-compiled in the Stage 1 Build-Class
148     * {@link S01_JavaCompiler}.
149     * 
150     * @param builder This instance contains all information obtained from the User via the
151     * User-Settings class {@link Config}, and information obtained via the Command-Line
152     * Interface {@link CLI}.
153     * 
154     * @return The list of packages whose files are to be recompiled, based on the User-Settings
155     * provided class {@link Config}, and the User-Request that were made at the {@link CLI}, 
156     * Command-Line Interface
157     */
158    public static ReadOnlyList<BuildPackage> packagesToCompile(Builder builder) throws IOException
159    {
160        // It is important to "get" the BuildPackage Configuration-Flags.  
161        //
162        // The value of BuildPackge.mustReCompile is defined in (surprise) class BuildPackage, as
163        // follows, here:
164        //
165        // this.earlyDevelopment   = (flags & EARLY_DEVELOPMENT) >= 1;
166        // this.skipIfQuickerBuild = (flags & QUICKER_BUILD_SKIP)  >= 1;
167        // 
168        // this.mustReCompile =
169        //         (! this.earlyDevelopment)
170        //     &&  (! this.skipIfQuickerBuild)
171        //     &&  ((flags & DO_NOT_RECOMPILE) == 0); // == 0 implies the "NOT" of the flag
172        //
173        // FINALLY: The cli.userSpecifiedPackages is literally just the Package-NickNames tht are
174        //          provided to class CLI via the "public static void main" method that gets it.
175
176        final boolean IS_FULL_COMPILE = (builder.cli.userSpecifiedPackages == null);
177
178        final Predicate<BuildPackage> FILT = (builder.cli.INCLUDE_EARLY_DEV_PACKAGES)
179            ? (BuildPackage bp) -> bp.mustReCompile || bp.earlyDevelopment
180            : (BuildPackage bp) -> bp.mustReCompile;
181
182        final ReadOnlyList<BuildPackage> packagesToCompile = IS_FULL_COMPILE
183            ? new ReadOnlyArrayList<>(builder.packageList, FILT, builder.packageList.size())
184            : builder.cli.userSpecifiedPackages;
185
186        return packagesToCompile;
187    }
188
189    /**
190     * This determines which packages should be run through {@code 'javadoc'}, in the Stage 2
191     * Build-Class {@link S02_JavaDoc}.
192     * 
193     * @param builder This instance contains all information obtained from the User via the
194     * User-Settings class {@link Config}, and information obtained via the Command-Line
195     * Interface {@link CLI}.
196     * 
197     * @return The list of packages whose files are to be sent to the {@code javadoc} Tool, based
198     * on the User-Settings provided class {@link Config}, and the User-Request that were made at
199     * the {@link CLI}, Command-Line Interface.
200     */
201    public static ReadOnlyList<BuildPackage> packagesToJavaDoc(Builder builder)
202    {
203        // Copied from the class `BuildPackage
204        //
205        // this.mustDocument        = (flags & DO_NOT_DOCUMENT)     == 0; // The "NOT" of the flag
206        // this.earlyDevelopment    = (flags & EARLY_DEVELOPMENT)   >= 1;
207        // this.skipIfQuickerBuild  = (flags & QUICKER_BUILD_SKIP)  >= 1;
208
209        final Predicate<BuildPackage> FILT = (BuildPackage pkg) -> pkg.mustDocument;
210
211        final ReadOnlyList<BuildPackage> ret = new ReadOnlyArrayList<>
212            (builder.packageList, FILT, builder.packageList.size());
213
214        return ret;
215    }
216}