Package Torello.Java

Class FileTransfer


  • public class FileTransfer
    extends java.lang.Object
    Operating-System independent utilities for moving, copying and deleting files, or an entire tree of files - using the FileNode class.

    This class allows a user to copy directories of files, and even entire sub-directory-trees of files from a source directory on the underlying file-system to a target-directory.


    FileNode-Tree Changes:
    The file-moving (file-transfer) methods provided in this class will not modify or manipulate the FileNode-Tree in any way whatsoever. In order to maintain consistency with the File-System, it would be smarter, after a file delete, move, copy or transfer operation, to reload the FileNode-Tree structure again, from disk.

    Again, in order to to make sure that the FileNode-Tree being used actually mirrors the underlying File-System's structure, the programmer must perform another loadTree(...) call after any / all move, delete & copy operations have been completed.


    Redundancy & WORA:
    This class is (somewhat) a "redundant version" of the class Shell found within this same package. This class can do many of the move and copy operations that are done there.

    This class, though, is Operating-System Independent - meaning that it fulfills Java's Standard WORA Pledage. The methods in class Shell work specifically on UNIX Platforms only.



    Here, below, is a sample use if a 'delete' method from this class:

    Example:
    import Torello.Java.FileTransfer;
    
    // The following commands delete all files in the directory-named by the string below:
    // Log information will be sent to the terminal (System.out)
    
    FileNode fn = FileNode
        .createRoot("some/directory/mydir/")
        .loadTree();
    
    FileTransfer.deleteFilesRecursive(fn, null, null, System.out);
    



    Stateless Class:
    This class neither contains any program-state, nor can it be instantiated. The @StaticFunctional Annotation may also be called 'The Spaghetti Report'. Static-Functional classes are, essentially, C-Styled Files, without any constructors or non-static member fields. It is a concept very similar to the Java-Bean's @Stateless Annotation.

    • 1 Constructor(s), 1 declared private, zero-argument constructor
    • 6 Method(s), 6 declared static
    • 0 Field(s)


    • Method Detail

      • copy

        🡇         External-Java:    🗕  🗗  🗖
        public static int copy​(FileNode directory,
                               FileNodeFilter filter,
                               java.lang.String targetDirectory,
                               java.lang.Appendable a)
                        throws java.io.IOException,
                               SameSourceAndTargetException,
                               java.nio.file.InvalidPathException,
                               java.nio.file.NoSuchFileException
        Copies the contents of one directory to another. Avoids copying files that do not pass the filter test. This method will only copy files and will avoid copying any sub-directories to the target directory.

        Example:
        // This loads all available files in the 'javadoc/' directory-tree for package Torello.HTML
        FileNode fn = FileNode
            .createRoot("javadoc/Torello/HTML/")
            .loadTree();
        
        
        // This will copy all '.html' files in directory 'javadoc/Torello/HTML/' to a temp directory.
        // Log information (copy messages) will be printed to standard-out.  If the programmer is on a
        // UNIX system, they will be colorized using UNIX terminal color-codes.
        // NOTE: The directory 'temp/' must have already been created.
        
        FileTransfer.copy(fn, f -> f.name.endsWith(".html"), "temp/", System.out);
        
        Parameters:
        directory - This must be a "directory" not a "file" instance of FileNode or an exception shall be thrown. If this class is a directory, then every file that is currently in this directory shall be copied to the 'targetDirectory.' This parameter may not be null.
        filter - This parameter may be null, but if it is not, each file will be tested by this java-lambda for identifying whether or not it meets the "accept" or "reject" interface before copying is performed.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) should return TRUE to indicate that the file being predicated must be copied. FALSE needs to be returned if the file should not be copied.
        targetDirectory - Where the files shall be copied. This must be a valid directory as well, or else a FileNotFoundException shall throw. This method will not create this directory if it does not exist. See method java.io.File.mkdirs() for information on how to create files on the file-system.

        Note: It is expected that the last character in this String contain a directory-separator character (on UNIX, this is the forward-slash ('/') and in MS-DOS & Windows this is the back-slash ('\'). If this character is not present, if this String does not 'end-with' a java.io.File.separator then one will be appended to the end of this String.
        a - This parameter may be null, but if it is not, then debugging / logging / informational messages will be sent to this output. This expects an implementation of Java's java.lang.Appendable interface which allows for a wide range of options when logging intermediate messages.
        Class or Interface Instance Use & Purpose
        'System.out' Sends text to the standard-out terminal
        Torello.Java.StorageWriter Sends text to System.out, and saves it, internally.
        FileWriter, PrintWriter, StringWriter General purpose java text-output classes
        FileOutputStream, PrintStream More general-purpose java text-output classes

        Checked IOException:
        The Appendable interface requires that the Checked-Exception IOException be caught when using its append(...) methods.
        Returns:
        The number of files that were copied.
        Throws:
        DirExpectedException - If you pass a "file" instance of class FileNode to parameter 'directory.'
        WritableDirectoryException - If the target-directory is not available to Java for copying.
        java.nio.file.NoSuchFileException - This will be thrown if the logic which checks to ensure that the source and target directories are not identical is unable to identify the real path name of either the source or target directory. One such possible situation where this would happen would be if the user applied the UNIX tilda ('~') in either the source or target directory-name.
        java.nio.file.InvalidPathException - This will be thrown if class java.nio.file.Paths is unable to instantiate a java.nio.file.Path for either the source-directory (parameter directory), or the targetDirectory.
        SameSourceAndTargetException - This will be thrown if the source and target directories are found to point to identical locations on the file-system.
        java.io.IOException - For any IO filesystem errors.
        See Also:
        copyRecursive(FileNode, FileNodeFilter, FileNodeFilter, String, Appendable), FileNode.getDirContentsFiles(RTC), DirExpectedException.check(FileNode), WritableDirectoryException.check(String), SameSourceAndTargetException.check(FileNode, String)
        Code:
        Exact Method Body:
         DirExpectedException.check(directory);
         WritableDirectoryException.check(targetDirectory);
         SameSourceAndTargetException.check(directory, targetDirectory);
        
         final String td = targetDirectory.endsWith(File.separator)
             ? targetDirectory
             : targetDirectory + File.separator;
        
         return CopyFiles.COPY(directory, filter, td, a);
        
      • copyRecursive

        🡅  🡇         External-Java:    🗕  🗗  🗖
        public static int copyRecursive​(FileNode directory,
                                        FileNodeFilter fileFilter,
                                        FileNodeFilter dirFilter,
                                        java.lang.String targetDirectory,
                                        java.lang.Appendable a)
                                 throws java.io.IOException,
                                        SameSourceAndTargetException,
                                        java.nio.file.InvalidPathException,
                                        java.nio.file.NoSuchFileException
        Copies an entire directory tree to a target-directory. Note, this class will use the java.io.File.mkdirs() method to create any sub-directories that exists in the Source-Directory Tree, but not in the Target-Directory Tree.
        Parameters:
        directory - This is the source or "root node" of the directory-tree that needs to be (recursively) copied to the 'targetDirectory'. This FileNode must be a directory, or else an DirExpectedException will be thrown. This parameter may not be null.
        fileFilter - If the programmer using this method would like to maintain some control in deciding which files are copied - copying some, but not others - to the destination / target-directory, the provide a Java Predicate which makes decisions on which files to copy to the target-directory, and which files to leave out of the copy process.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) will return TRUE to indicate that the predicated file needs to be copied. This predicate should return FALSE if copying isn't necessary.

        Note: This parameter may be null, and if it is it shall simply be ignored. This is the default behavior. In this situation, all files found in each-and-every-level of the source directory tree will be copied to the target-directory.
        dirFilter - If the programmer using this method would like to skip entire branches of the source directory tree, then implement a java predicate that identifies which sub-directories (read: 'branches') of the source directory-tree should be skipped. This parameter (a java.util.function.Predicate<FileNode>) shall receive file-system directories (not files!) as input to its public boolean test() method, and if this method returns FALSE, the branch that was passed to the Predicate shall be skipped entirely by this copy-routine.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) should return TRUE to indicate that a sub-directory in question should be traversed and copied. FALSE must be returned by this filter to skip and remove, entirely, the named sub-directory from the copy process.

        Note: If this parameter is null, it shall just be ignored. This is the default behavior. When this parameter is null, all branches (all sub-directories) of the FileNode parameter 'fn' will be copied to 'targetDirectory'.

        Subtle Note: The following two examples will hopefully clarify an issue about filters. The parameter 'fileFilter' is, in most cases, more useable than the 'dirFilter' parameter.

        The 'dirFilter' will force a skip of an entire branch of the directory tree (not traversing the sub-directory). See this example below where the programmer is attempting to copy all files/classes in the javadoc/Torello/HTML/NodeSearch/ directory that have the word 'TagNode'


        Example:
        // These lines will load the "javadoc" documentation files for this jar into a FileNode Tree.
        // These are mostly the '.html' files for the code-documentation you are reading right now.
        FileNode fn = FileNode
             .createRoot("javadoc/")
             .loadTree();
        
        // THIS WILL FAIL to copy the "TagNode" files in the "NodeSearch" directory to 'temp/'
        FileTransfer.copyRecursive(
             fn,
             f -> f.toString().contains("TagNode"),      // Expecting any file having "TagNode" in it's name
             f -> f.toString().contains("NodeSearch"),   // Supposedly expecting directories having "NodeSearch" in their name
             "temp/", System.out
        );
        // FAILS TO COPY ANY FILES: The directory predicate BLOCKED the first sub-directory from loading!
        
        
        // THIS WILL SUCCEED
        FileTransfer.copyRecursive(
             fn,
             f -> StrCmpr.containsAND(f.toString(), "TagNode", "NodeSearch"),     
             null,
             "temp/", System.out
        );
        
        // This SUCCEEDS since the f.toString() method will return the FULL PATH NAME of any file.
        // File's having "TagNode" or "NodeSearch" in their file name, or sub-directory path will result
        // in the file predicate returning TRUE.  16 Files here will be copied to 'temp/'
        // NOTE:  The files are javadoc/Torello/HTML/NodeSearch/TagNodeFind.html, and others...
        
        targetDirectory - Where the files shall be copied. This must be a valid directory as well, or else a FileNotFoundException shall throw. This method will not create this directory if it does not exist. See method java.io.File.mkdirs()\ for information on how to create files on the file-system.

        Note: It is expected that the last character in this String contain a directory-separator character (on UNIX, this is the forward-slash ('/') and in MS-DOS & Windows this is the back-slash ('\'). If this character is not present, if this String does not 'end-with' a java.io.File.separator then one will be appended to the end of this String.
        a - This parameter may be null, but if it is not, then debugging / logging / informational messages will be sent to this output.
        Returns:
        This method makes calls to the single-level, single-directory-version of the copy(...) method in this class for each directory found in the tree. This method shall sum-up all and count all the files as they are copied. The value returned by this method is an integer specified how many files were copied in the process.
        Throws:
        DirExpectedException - If you pass a "file" instance of class FileNode to parameter 'directory.'
        WritableDirectoryException - If the initial target-directory, itself, is not available to Java for copying, then this exception shall throw. In actuality, all sub-directories that need to be created will be created by this recursive-copy operation - except for the highest-level "top directory" (the one indicated by the parameter 'targetDirectory' - because if that doesn't exist, then this 'WritableDirectoryException' will throw).
        java.nio.file.NoSuchFileException - This will be thrown if the logic which checks to ensure that the source and target directories are not identical is unable to identify the real path name of either the source or target directory. One such possible situation where this would happen would be if the user applied the UNIX tilda ('~') in either the source or target directory-name.
        java.nio.file.InvalidPathException - This will be thrown if class java.nio.file.Paths is unable to instantiate a java.nio.file.Path for either the source-directory (parameter directory), or the targetDirectory.
        SameSourceAndTargetException - This will be thrown if the source and target directories are found to point to identical locations on the file-system.
        java.io.IOException - For any IO filesystem errors.
        See Also:
        copy(FileNode, FileNodeFilter, String, Appendable), FileNode.getDirContentsDirs(RTC), DirExpectedException.check(FileNode), WritableDirectoryException.check(String), SameSourceAndTargetException.check(FileNode, String)
        Code:
        Exact Method Body:
         DirExpectedException.check(directory);
         WritableDirectoryException.check(targetDirectory);
         SameSourceAndTargetException.check(directory, targetDirectory);
        
         final String td = targetDirectory.endsWith(File.separator)
             ? targetDirectory 
             : targetDirectory + File.separator;
        
         return CopyFiles.RECURSIVE(directory, fileFilter, dirFilter, td, a);
        
      • deleteFiles

        🡅  🡇         External-Java:    🗕  🗗  🗖
        public static int deleteFiles​(FileNode directory,
                                      FileNodeFilter filter,
                                      java.lang.Appendable a)
                               throws java.io.IOException
        This method will delete files (not sub-directories) from a source directory. This method is not recursive, and will not delete files from sub-directories. Files in all other directories of the sub-directory branch that begins with the FileNode parameter 'directory' shall all be left-alone, except the files inside the contents of parameter 'directory' itself.
        Parameters:
        directory - This is the source or "root node" of the directory-tree that needs to be (recursively) deleted. This FileNode must be a directory, or else a DirExpectedException will be thrown. This parameter may not be null.
        filter - If the programmer using this method would like to maintain some control in deciding which files are deleted - deleting some, but not others - from 'directory', then he / she should provide a java.util.function.Predicate<FileNode> here using the 'filter' parameter which makes decisions on which files to delete, and which to leave alone.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) should return TRUE) to indicate that the file in question must be deleted, and FALSE if no delete is necessary.

        Note: This parameter may be null, and if it is, it shall be ignored. In this situation, every file found within 'directory' will be removed from the file-system.
        a - An output log, for debugging & logging informational messages. This parameter may be null, and if so, it will be silently ignored. This expects an implementation of Java's java.lang.Appendable interface which allows for a wide range of options when logging intermediate messages.
        Class or Interface Instance Use & Purpose
        'System.out' Sends text to the standard-out terminal
        Torello.Java.StorageWriter Sends text to System.out, and saves it, internally.
        FileWriter, PrintWriter, StringWriter General purpose java text-output classes
        FileOutputStream, PrintStream More general-purpose java text-output classes

        Checked IOException:
        The Appendable interface requires that the Checked-Exception IOException be caught when using its append(...) methods.
        Returns:
        An integer that reports how many files were deleted from the file-system.

        Note: Only files will be deleted by this method. No directories shall be removed. Also, the only files that shall be deleted are those which are direct-descendants of FileNode parameter 'directory'. This method is not recursive, and the directory tree will neither be entered nor traversed.
        Throws:
        DirExpectedException - If you pass a "file" instance of class FileNode to parameter 'directory'.
        java.io.IOException - For any IO file-system errors.
        See Also:
        deleteFilesRecursive(FileNode, FileNodeFilter, FileNodeFilter, Appendable), FileNode.getDirContentsFiles(RTC), FileNode.getJavaIOFile(), DirExpectedException.check(FileNode)
        Code:
        Exact Method Body:
         DirExpectedException.check(directory);
         return DeleteFiles.DELETE(directory, filter, a);
        
      • deleteFilesRecursive

        🡅  🡇         External-Java:    🗕  🗗  🗖
        public static int deleteFilesRecursive​(FileNode directory,
                                               FileNodeFilter fileFilter,
                                               FileNodeFilter dirFilter,
                                               java.lang.Appendable a)
                                        throws java.io.IOException
        Deletes files sub-directories from a FileNode.

        Deletion Behavior:
        When, after a delete, a directory or sub-directory is not empty because the User-Provided Filters requested to skip the deletion of some of the sub-diretories or files, this method will therefore be unable to remove these sub-directory branches from the File-System.

        This behavior is largely consistent with standard UNIX and MS-DOS commands such as 'cp', 'mv', 'copy' etc... Under these Operating-Systems, non-empty directories cannot be deleted until their contents have been removed completely.

        Appendable Log:
        If a non-null Appendable (log) is passed to this method, notices are provided to the user as directories are removed. This may be of use for later reviewing what was deleted, and what was retained.
        Parameters:
        directory - This is the source or "root node" of the directory-tree that needs to be (recursively) deleted. This parameter may not be null. This FileNode must be a directory, or else a DirExpectedException will be thrown.
        fileFilter - If the programmer using this method would like to maintain some control in deciding which files are deleted, then he/she must provide a Java java.util.function.Predicate<FileNode> which makes these decisions regarding which files to remove, and which files to leave alone.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) should return TRUE to indicate that the predicated file should be deleted. This filter-Predicate must return FALSE if a delete isn't necessary.

        Note: This parameter may be null, and if it is, it shall be ignored. This is the default behavior. In this situation, all files found in each-and-every-level of the source directory tree will be deleted.
        dirFilter - If the programmer using this method would like to skip entire branches of the source directory tree, then implement a java predicate that identifies which sub-directories (read: 'branches') of the source directory-tree should be skipped. This parameter (a java.util.function.Predicate<FileNode>) shall receive file-system directories (not files!) as input to its public boolean test() method, and if this method returns FALSE, the branch that was passed to the Predicate shall be skipped entirely by this delete-routine.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) should return TRUE to indicate that a sub-directory in question needs to be traversed and deleted. This filter-Predicate must return FALSE if a sub-directory should be skipped and ignored entirely during the deletion process.

        Note: If this parameter is null, it shall just be ignored. This is the default behavior. When this parameter is null, all branches (all sub-directories) of the FileNode parameter 'fn' will be put through the recursive deletion process.
        a - An output log, for debugging & logging informational messages. This parameter may be null, and if so, it will be silently ignored.
        Returns:
        This method will return an integer that reports how many files were deleted. It might be important to note that when sub-directories are deleted, they are only deleted because they were empty. Any non-empty sub-directory will be left alone, and not removed. Also, when files are deleted, they add to the "total delete count" which is the output integer from this method. However, when directories are deleted, their deletion does not contribute to the output-count.
        Throws:
        DirExpectedException - If you pass a "file" instance of class FileNode to parameter 'directory'
        java.io.IOException - For any IO file-system errors.
        See Also:
        deleteFiles(FileNode, FileNodeFilter, Appendable), FileNode.getDirContentsDirs(RTC), FileNode.getJavaIOFile(), DirExpectedException.check(FileNode)
        Code:
        Exact Method Body:
         DirExpectedException.check(directory);
         return DeleteFiles.RECURSIVE(directory, fileFilter, dirFilter, a);
        
      • move

        🡅  🡇         External-Java:    🗕  🗗  🗖
        public static int move​(FileNode directory,
                               FileNodeFilter filter,
                               java.lang.String targetDirectory,
                               java.lang.Appendable a)
                        throws java.io.IOException,
                               SameSourceAndTargetException,
                               java.nio.file.InvalidPathException,
                               java.nio.file.NoSuchFileException
        Moves the contents of one directory to another. Avoids moving files that do not pass the 'filter' test. If a log parameter ('a') is provided, textual status-updates will be printed to that log.

        Method Heuristic
        All this method does is to perform, sequentially:

        1. A copy operation of a file to a new directory.
        2. A delete operation on the file from the original location.
        Parameters:
        directory - This must be a "directory" not a "file" instance of class FileNode, or an exception shall throw. If this class is a directory, then every file that is currently in this directory shall be copied to the 'targetDirectory' - and then deleted from this directory. This parameter may not be null, or NPE will throw.
        targetDirectory - Where the files shall be moved. This must be a valid directory as well, or else a FileNotFoundException shall throw. This method will not create this directory if it does not exist. See method java.io.File.mkdirs() for information on how to create files on the file-system.

        Note:It is expected that the last character in this String contain a directory-separator character (on UNIX, this is the forward-slash ('/') and in MS-DOS & Windows this is the back-slash ('\'). If this character is not present, if this String does not 'end-with' a java.io.File.separator then one will be appended to the end of this String.
        filter - This parameter may be null, but if it is not, each file will be tested to see whether or not it meets this User-Specified "accept or reject" criteria before moving is performed.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) should return TRUE to indicate that the file in question needs to be moved. This filter-Predicate must return FALSE if a move isn't necessary.
        a - An output log, for debugging & logging informational messages. This parameter may be null, and if so, it will be silently ignored. This expects an implementation of Java's java.lang.Appendable interface which allows for a wide range of options when logging intermediate messages.
        Class or Interface Instance Use & Purpose
        'System.out' Sends text to the standard-out terminal
        Torello.Java.StorageWriter Sends text to System.out, and saves it, internally.
        FileWriter, PrintWriter, StringWriter General purpose java text-output classes
        FileOutputStream, PrintStream More general-purpose java text-output classes

        Checked IOException:
        The Appendable interface requires that the Checked-Exception IOException be caught when using its append(...) methods.
        Returns:
        The number of files that were moved.
        Throws:
        DirExpectedException - If you pass a "file" instance of class FileNode to parameter 'directory.'
        WritableDirectoryException - If the target-directory is not available to Java for moving.
        java.nio.file.NoSuchFileException - This will be thrown if the logic which checks to ensure that the source and target directories are not identical is unable to identify the real path name of either the source or target directory. One such possible situation where this would happen would be if the user applied the UNIX tilda ('~') in either the source or target directory-name.

        This check is crucial since when performing a MOVE operation, the contents of a directory are first copied, and then deleted. If the source and target directories are identical, then after the initial copy operation, the logic would simply delete the original files.
        java.nio.file.InvalidPathException - This will be thrown if class java.nio.file.Paths is unable to instantiate a java.nio.file.Path for either the source-directory (parameter directory), or the targetDirectory.
        SameSourceAndTargetException - This will be thrown if the source and target directories are found to point to identical locations on the file-system. Since this is a MOVE operation, when moving files, the logic first copies the files and then deletes the originals. If the source and target directories are identical, after the initial COPY operation completes, the logic would simple erase those originals - which would destroy both copies!
        java.io.IOException - For any IO file-system errors.
        See Also:
        moveRecursive(FileNode, FileNodeFilter, FileNodeFilter, String, Appendable), DirExpectedException.check(FileNode), WritableDirectoryException.check(String), SameSourceAndTargetException.check(FileNode, String)
        Code:
        Exact Method Body:
         DirExpectedException.check(directory);
         WritableDirectoryException.check(targetDirectory);
         SameSourceAndTargetException.check(directory, targetDirectory);
        
         final String td = targetDirectory.endsWith(File.separator)
             ? targetDirectory 
             : targetDirectory + File.separator;
        
         return MoveFiles.MOVE(directory, filter, td, a);
        
      • moveRecursive

        🡅         External-Java:    🗕  🗗  🗖
        public static int moveRecursive​(FileNode directory,
                                        FileNodeFilter fileFilter,
                                        FileNodeFilter dirFilter,
                                        java.lang.String targetDirectory,
                                        java.lang.Appendable a)
                                 throws java.io.IOException,
                                        SameSourceAndTargetException,
                                        java.nio.file.InvalidPathException,
                                        java.nio.file.NoSuchFileException
        Copies an entire directory tree to a target-directory, and the removes the original files & directories from their original location. Note, this class will use the java.io.File.mkdirs()' method to create any sub-directories which are present in the source-directory-tree but not are not present in the target-directory-tree.

        Move Behavior:
        When, after a move, a sub-directory is not be completely empty because the filters have elected not to skip moving some of files or sub-directories, then this method be will be unable to remove the old-copies of those directory-branches of the file-system tree.

        This behavior is largely consistent with standard UNIX and MS-DOS commands such as 'cp', 'mv', 'copy' etc... Under these Operating-Systems, non-empty directories cannot be deleted until their contents have been removed completely.

        Appendable Log:
        If a non-null Appendable (log) is passed to this method, notices are provided to the user as directories are removed. This may be of use for later reviewing what was deleted, and what was retained.
        Parameters:
        directory - This is the source or "root node" of the directory-tree that needs to be (recursively) copied to the 'targetDirectory'. This FileNode must be a directory, or else an DirExpectedException will be thrown. This parameter may not be null.
        targetDirectory - Where the files shall be moved. This must be a valid directory as well, or else a FileNotFoundException shall throw. This method will not create this directory if it does not exist. See method java.io.File.mkdirs() for information on how to create files on the file-system.

        Note: It is expected that the last character in this String contain a directory-separator character (on UNIX, this is the forward-slash ('/') and in MS-DOS, Windows this is the back-slash (''). If this character is not present, if this String does not 'end-with' a java.io.File.separator then one will be appended to the end of this String.
        fileFilter - If the programmer using this method would like to skip entire branches of the source directory tree, then implement a java predicate that identifies which sub-directories (read: 'branches') of the source directory-tree should be skipped. This parameter (a java.util.function.Predicate<FileNode>) shall receive file-system directories (not files!) as input to its public boolean test() method, and if this method returns FALSE, the branch that was passed to the Predicate shall be skipped entirely by this move-routine.

        Filter Predicate Behavior: This filter (Predicate<FileNode>) needs to return TRUE in order to signal that the predicated sub-directory should be traversed and moved. The Predicate must return FALSE in order to request that the predicated sub-directory is to be skipped and eliminated entirely from the recursive move process.

        Note: If this parameter is null, it will simply be ignored. This is the default behavior. When this parameter is null, all branches (all sub-directories) of the FileNode parameter 'fn' shall be copied to the target directory.
        dirFilter - If the programmer using this method would like to maintain some control in deciding which files are copied - copying some, but not others - to the destination / target-directory, the provide a Java java.util.function.Predicate<FileNode> which makes decisions on which files to copy to 'targetDirectory', and which files to leave out of the copy process.

        Filter Predicate Behavior: This filter Predicate<FileNode> needs to return TRUE in order to signal that the predicated file must be moved. This Predicate should return FALSE if a move isn't necessary for the file in question.

        Note: This parameter may be null, and if it is it shall just be ignored. This is the default behavior of this method. In this situation, all files found in each-and-every-level of the source directory tree will be copied to the targetDirectory.
        a - An output log, for debugging & logging informational messages. This parameter may be null, and if so, it will be silently ignored.
        Returns:
        This method makes calls to the single-level, single-directory-version of the 'copy(...)' method in this class for each directory found in the tree. This method shall sum-up all and count all the files as they are copied. The value returned by this method is an integer specified how many files were copied in the process.
        Throws:
        DirExpectedException - If you pass a "file" instance of class FileNode to parameter 'directory.'
        WritableDirectoryException - If the initial target-directory, itself, is not available to Java for copying, then this exception shall throw. In actuality, all sub-directories that need to be created will be created by this recursive-copy operation - except for the highest-level "top directory" (the one indicated by the parameter 'targetDirectory' - because if that doesn't exist, then a 'WritableDirectoryException' ill throw).
        java.nio.file.NoSuchFileException - This will be thrown if the logic which checks to ensure that the source and target directories are not identical is unable to identify the real path name of either the source or target directory. One such possible situation where this would happen would be if the user applied the UNIX tilda ('~') in either the source or target directory-name.

        This check is crucial since when performing a MOVE operation, the contents of a directory are first copied, and then deleted. If the source and target directories are identical, then after the initial copy operation, the logic would simply delete the original files.
        java.nio.file.InvalidPathException - This will be thrown if class java.nio.file.Paths is unable to instantiate a java.nio.file.Path for either the source-directory (parameter directory), or the targetDirectory.
        SameSourceAndTargetException - This will be thrown if the source and target directories are found to point to identical locations on the file-system. Since this is a MOVE operation, when moving files, the logic first copies the files and then deletes the originals. If the source and target directories are identical, after the initial COPY operation completes, the logic would simple erase those originals - which would destroy both copies!
        java.io.IOException - For any IO filesystem errors.
        See Also:
        move(FileNode, FileNodeFilter, String, Appendable), FileNode.getDirContentsDirs(RTC), DirExpectedException.check(FileNode), WritableDirectoryException.check(String), SameSourceAndTargetException.check(FileNode, String)
        Code:
        Exact Method Body:
         DirExpectedException.check(directory);
         WritableDirectoryException.check(targetDirectory);
         SameSourceAndTargetException.check(directory, targetDirectory);
        
         final String td = targetDirectory.endsWith(File.separator)
             ? targetDirectory 
             : targetDirectory + File.separator;
        
         return MoveFiles.RECURSIVE(directory, fileFilter, dirFilter, td, a);