001package Torello.Java.Build;
002
003import Torello.Java.StringParse;
004import Torello.Java.FileNode;
005import Torello.Java.RTC;
006
007import Torello.Java.Additional.Counter;
008
009import java.io.File;
010import java.io.FilenameFilter;
011import java.io.IOException;
012
013import java.util.ArrayList;
014import java.util.function.Predicate;
015
016import Torello.Java.ReadOnly.ROArrayListBuilder;
017import Torello.Java.ReadOnly.ROHashtableBuilder;
018import Torello.Java.ReadOnly.ReadOnlyList;
019import Torello.Java.ReadOnly.ReadOnlyArrayList;
020
021import Torello.Java.StrCSV;
022
023import static Torello.Java.C.BRED;
024import static Torello.Java.C.RESET;
025
026/**
027 * Given a list of Java-Packages, this class will collate a list of files to be processed.
028 * 
029 * <BR /><BR />This class is a utility used internally by the following Build-Stages:
030 *
031 * <BR /><BR /><UL CLASS=JDUL>
032 * <LI>Compilation / Stage-1</LI>
033 * <LI>Documentation / Java-Doc / Stage-2</LI>
034 * </UL>
035 * 
036 * <BR />
037 * <EMBED CLASS='external-html' DATA-FILE-ID=INTERNAL_CLASS_NOTE>
038 */
039@Torello.JavaDoc.StaticFunctional
040public class Files
041{
042    // Completely irrelevant, and the 'private' modifier keeps it off of JavaDoc
043    private Files() { }
044
045    private static final String FS = File.separator;
046
047
048    // ********************************************************************************************
049    // ********************************************************************************************
050    // File-Array Builder
051    // ********************************************************************************************
052    // ********************************************************************************************
053
054
055    private static final int addMore(
056            final ROArrayListBuilder<String>    b,
057            final String                        dir,
058            final boolean                       depth,
059            final FilenameFilter                filter
060        )
061    {
062        Counter c = new Counter(0);
063
064        FileNode
065            .createRoot         (dir)
066            .loadTree           (depth ? -1 : 0, filter, null)
067            .flattenJustFiles   (RTC.FULLPATH_VECTOR())
068            .forEach            ((String srcFileName) -> { c.addOne(); b.add(srcFileName); });
069
070        return c.get();
071    }
072
073
074    // ********************************************************************************************
075    // ********************************************************************************************
076    // Stage 01, Compile Files
077    // ********************************************************************************************
078    // ********************************************************************************************
079
080
081    /**
082     * Retrieve the Stage 1 Files List of {@code '.java'} Files.  The master list that is returned
083     * as a result of this method is the complete list of files sent to {@code 'javac'}, as command
084     * line parameters.
085     * 
086     * @param packagesToCompile The list of packages whose files need to be compiled.  This list,
087     * itself, was built by class {@link Packages} method
088     * {@link Packages#packagesToCompile(BuilderRecord) builder} using all User-Provided
089     * Configurations, and Command-Line Switch Choices.
090     * 
091     * @param logAndScreen Prints log information to both the log and the terminal-screen.
092     * 
093     * @return The list of files to be compiled by the Stage 1 Build-Class
094     * {@link S01_JavaCompiler}.
095     * 
096     * @throws IOException Required due to the {@code Appendable} parameter {@code 'logAndScreen'}
097     * @see Printing#printFilesCount(ReadOnlyList, ArrayList, Appendable)
098     */
099    static ReadOnlyList<String> filesToCompile(
100            final ReadOnlyList<BuildPackage>    packagesToCompile,
101            final Appendable                    logAndScreen
102        )
103        throws IOException
104    {
105        // This is much easier to understand.  It is actually smarter to just go to the class
106        // "Files" and look what it is doing.  The loop that collects the files for a "Package"
107        // uses the following BuildPackage boolean-fields, which are defined, as below, inside the
108        // BuildPackage-Constructor:
109        //
110        // BuildPackage.hasSubPackages     = (flags & HAS_SUB_PACKAGES)    >= 1;
111        // BuildPackage.pkgRootDirectory   = classPathLocation + fullName.replace(".", FS) + FS;
112        //
113        // this.helperPackages = (helperPackages == null) || (helperPackages.length == 0)
114        //     ? EMPTY_LIST
115        //     : ReadOnlyList.of(helperPackages);
116        //
117        // Just go to class "Files" to see how those "BuildPackage" boolean Configuration-Fields
118        // pick files to insert into the "filesToCompile" list.
119
120        // This keeps a complete list of all files that will need to be compiled
121        ROArrayListBuilder<String> roalb = new ROArrayListBuilder<>();
122
123        // This is used for printing to the screen only, it is discarded when this method
124        // exits.
125
126        final ArrayList<Integer> packageFilesCount = new ArrayList<>(packagesToCompile.size());
127
128        for (final BuildPackage pkg : packagesToCompile)
129        {
130            int count = 0;
131
132            count += addMore(roalb, pkg.pkgRootDirectory, pkg.hasSubPackages, FileNode.JAVA_FILES);
133
134            if (pkg.hasUpgradeFilesDir) count += addMore
135                (roalb, pkg.pkgRootDirectory + "upgrade-files" + FS, true, FileNode.JAVA_FILES);
136
137            if (pkg.hasPackageSourceDir) count += addMore
138                (roalb, pkg.pkgRootDirectory + "package-source" + FS, true, FileNode.JAVA_FILES);
139
140            for (String helperPkgDirName : pkg.helperPackages) count += addMore
141                (roalb, helperPkgDirName, false, FileNode.JAVA_FILES);
142
143            packageFilesCount.add(Integer.valueOf(count));
144        }
145
146
147        // Prints out the number of '.java' Files that were found, in each of the
148        // package-directories.
149        // 
150        // TRUE ==> '.java' Files (FALSE ==> '.class' Files)
151
152        Printing.printFilesCount(packagesToCompile, packageFilesCount, logAndScreen, true);
153
154        return roalb.build();
155    }
156
157
158    // ********************************************************************************************
159    // ********************************************************************************************
160    // Stage 01, Optional-Action, First Delete '.class' Files.  Retrieve all '.class' File-Names
161    // ********************************************************************************************
162    // ********************************************************************************************
163
164
165    // This method was Block-Copied (^C^V), directly from the previous method.  This meethod,
166    // instead of finding and retrieving all of the '.java' Files that need to be compiled, it
167    // retrieves the names of all of the old '.class' Files that are to be deleted, before the
168    // '.java' files are compiled.
169
170    static ReadOnlyList<String> classFilesToDeleteBeforeCompilation(
171            final ReadOnlyList<BuildPackage>    packagesToCompile,
172            final Appendable                    logAndScreen
173        )
174        throws IOException
175    {
176        ROArrayListBuilder<String> roalb = new ROArrayListBuilder<>();
177
178        final ArrayList<Integer> packageFilesCount = new ArrayList<>(packagesToCompile.size());
179
180        for (final BuildPackage pkg : packagesToCompile)
181        {
182            int count = 0;
183
184            count += addMore(roalb, pkg.pkgRootDirectory, pkg.hasSubPackages, FileNode.CLASS_FILES);
185
186            if (pkg.hasUpgradeFilesDir) count += addMore
187                (roalb, pkg.pkgRootDirectory + "upgrade-files" + FS, true, FileNode.CLASS_FILES);
188
189            if (pkg.hasPackageSourceDir) count += addMore
190                (roalb, pkg.pkgRootDirectory + "package-source" + FS, true, FileNode.CLASS_FILES);
191
192            for (String helperPkgDirName : pkg.helperPackages) count += addMore
193                (roalb, helperPkgDirName, false, FileNode.CLASS_FILES);
194
195            packageFilesCount.add(Integer.valueOf(count));
196        }
197
198
199        // Prints out the number of '.class' Files that were found, in each of the
200        // package-directories.
201        // 
202        // TRUE ==> '.java' Files, FALSE ==> '.class' Files
203
204        Printing.printFilesCount(packagesToCompile, packageFilesCount, logAndScreen, false);
205
206        return roalb.build();
207    }
208
209
210    // ********************************************************************************************
211    // ********************************************************************************************
212    // Stage 02, JavaDoc Files
213    // ********************************************************************************************
214    // ********************************************************************************************
215
216
217    /**
218     * Retrieve the Stage 1 Files List of {@code '.java'} Files.  The master list that is returned
219     * as a result of this method is the complete list of files sent to {@code 'javadoc'}, as
220     * command line parameters.
221     * 
222     * @param packagesToJavaDoc The list of packages whose files need to be compiled.  This list,
223     * itself, was built by class {@link Packages} method
224     * {@link Packages#packagesToCompile(BuilderRecord) builder} using all User-Provided
225     * Configurations, and Command-Line Switch Choices.
226     * 
227     * @param logAndScreen Prints log information to both the log and the terminal-screen.
228     * 
229     * @return The list of files to be compiled by the Stage 2 Build-Class
230     * {@link S02_JavaDoc}.
231     * 
232     * @throws IOException Required due to the {@code Appendable} parameter {@code 'logAndScreen'}
233     */
234    static ReadOnlyList<String> filesToJavaDoc(
235            final ReadOnlyList<BuildPackage>    packagesToJavaDoc,
236            final Appendable                    logAndScreen
237        )
238        throws IOException
239    {
240        // This keeps a complete list of all files that will need to be compiled
241        ROArrayListBuilder<String> roalb = new ROArrayListBuilder<>();
242
243        // This is used for printing to the screen only, it is discarded when this method
244        // exits.
245
246        final ArrayList<Integer> packageFilesCount = new ArrayList<>(packagesToJavaDoc.size());
247
248        for (final BuildPackage pkg : packagesToJavaDoc)
249        {
250            int count = 0;
251
252            count += addMore(roalb, pkg.pkgRootDirectory, false, FileNode.JAVA_FILES);
253
254            if (pkg.hasPackageSourceDir) count += addMore
255                (roalb, pkg.pkgRootDirectory + "package-source" + FS, true, FileNode.JAVA_FILES);
256
257            packageFilesCount.add(Integer.valueOf(count));
258        }
259
260
261        // Prints out the number of '.java' Files that were found, in each of the
262        // package-directories.
263        // 
264        // TRUE ==> '.java' Files (FALSE ==> '.class' Files)
265
266        Printing.printFilesCount(packagesToJavaDoc, packageFilesCount, logAndScreen, true);
267
268        return roalb.build();
269    }
270}