001package Torello.Java;
002
003import static Torello.Java.C.*;
004
005import java.util.*;
006
007import Torello.JavaDoc.LinkJavaSource;
008
009import java.io.*;
010import java.nio.file.*;
011
012/**
013 * Operating-System independent utilities for moving, copying and deleting files, or an entire
014 * tree of files - using the <CODE>FileNode</CODE> class.
015 * 
016 * <EMBED CLASS='external-html' DATA-FILE-ID=FILE_TRANSFER>
017 */
018@Torello.JavaDoc.StaticFunctional
019public class FileTransfer
020{
021    private FileTransfer() { }
022
023    /**
024     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_COPY_DESC>
025     * @param directory         <EMBED CLASS='external-html' DATA-FILE-ID=FT_COPY_DIRECTORY>
026     * @param filter            <EMBED CLASS='external-html' DATA-FILE-ID=FT_COPY_FILTER>
027     * @param targetDirectory   <EMBED CLASS='external-html' DATA-FILE-ID=FT_COPY_TARGET_DIR>
028     * 
029     * @param a This parameter may be null, but if it is not, then debugging / logging / 
030     * informational messages will be sent to this output.
031     * 
032     * <EMBED CLASS='external-html' DATA-FILE-ID=APPENDABLE>
033     *
034     * @return The number of files that were copied.
035     *
036     * @throws DirExpectedException If you pass a "file" instance of {@code class FileNode} to
037     * parameter {@code 'directory.'}
038     * 
039     * @throws WritableDirectoryException If the target-directory is not available to Java for
040     * copying.
041     * 
042     * @throws java.nio.file.NoSuchFileException This will be thrown if the logic which checks to
043     * ensure that the source and target directories are not identical is unable to identify the
044     * <I><B>real path name</B></I> of either the source or target directory.  One such possible 
045     * situation where this would happen would be if the user applied the UNIX <B>tilda
046     * ({@code '~'})</B> in either the {@code source} or {@code target} directory-name.
047     * 
048     * @throws java.nio.file.InvalidPathException This will be thrown if {@code class
049     * java.nio.file.Paths} is unable to instantiate a {@code java.nio.file.Path} for either the
050     * source-directory (parameter {@code directory}), or the {@code targetDirectory}.
051     * 
052     * @throws SameSourceAndTargetException This will be thrown if the source and target
053     * directories are found to point to identical locations on the file-system.
054     * 
055     * @throws IOException For any IO filesystem errors.
056     * 
057     * @see #copyRecursive(FileNode, FileNodeFilter, FileNodeFilter, String, Appendable)
058     * @see FileNode#getDirContentsFiles(RTC)
059     * @see DirExpectedException#check(FileNode)
060     * @see WritableDirectoryException#check(String)
061     * @see SameSourceAndTargetException#check(FileNode, String)
062     */
063    @LinkJavaSource(handle="CopyFiles")
064    public static int copy(
065            final FileNode          directory,
066            final FileNodeFilter    filter,
067            final String            targetDirectory,
068            final Appendable        a
069        )
070        throws IOException, SameSourceAndTargetException,
071            InvalidPathException, NoSuchFileException
072    {
073        DirExpectedException.check(directory);
074        WritableDirectoryException.check(targetDirectory);
075        SameSourceAndTargetException.check(directory, targetDirectory);
076
077        final String td = targetDirectory.endsWith(File.separator)
078            ? targetDirectory
079            : targetDirectory + File.separator;
080
081        return CopyFiles.COPY(directory, filter, td, a);
082    }
083
084    /**
085     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_CPREC_DESC>
086     * @param directory         <EMBED CLASS='external-html' DATA-FILE-ID=FT_CPREC_DIRECTORY>
087     * @param fileFilter        <EMBED CLASS='external-html' DATA-FILE-ID=FT_CPREC_FILE_FILT>
088     * @param dirFilter         <EMBED CLASS='external-html' DATA-FILE-ID=FT_CPREC_DIR_FILT>
089     * @param targetDirectory   <EMBED CLASS='external-html' DATA-FILE-ID=FT_CPREC_TARGET_DIR>
090     * 
091     * @param a This parameter may be null, but if it is not, then debugging / logging / 
092     * informational messages will be sent to this output.
093     *
094     * @return This method makes calls to the single-level, single-directory-version of the
095     * {@code copy(...)} method in this class for each directory found in the tree.  This method
096     * shall sum-up all and count all the files as they are copied.  The value returned by this
097     * method is an integer specified how many files were copied in the process.
098     *
099     * @throws DirExpectedException If you pass a "file" instance of {@code class FileNode} to
100     * parameter {@code 'directory.'}
101     *
102     * @throws WritableDirectoryException If the initial target-directory, itself, is not available
103     * to Java for copying, then this exception shall throw.  In actuality, all sub-directories 
104     * that need to be created will be created by this recursive-copy operation - except for the
105     * highest-level "top directory" (the one indicated by the parameter {@code 'targetDirectory'}
106     * - because if that doesn't exist, then this {@code 'WritableDirectoryException'} will throw).
107     * 
108     * @throws java.nio.file.NoSuchFileException This will be thrown if the logic which checks to
109     * ensure that the source and target directories are not identical is unable to identify the
110     * <I><B>real path name</B></I> of either the source or target directory.  One such possible 
111     * situation where this would happen would be if the user applied the UNIX <B>tilda
112     * ({@code '~'})</B> in either the {@code source} or {@code target} directory-name.
113     * 
114     * @throws java.nio.file.InvalidPathException This will be thrown if {@code class
115     * java.nio.file.Paths} is unable to instantiate a {@code java.nio.file.Path} for either the
116     * source-directory (parameter {@code directory}), or the {@code targetDirectory}.
117     * 
118     * @throws SameSourceAndTargetException This will be thrown if the source and target
119     * directories are found to point to identical locations on the file-system.
120     * 
121     * @throws IOException For any IO filesystem errors.
122     *
123     * @see #copy(FileNode, FileNodeFilter, String, Appendable)
124     * @see FileNode#getDirContentsDirs(RTC)
125     * @see DirExpectedException#check(FileNode)
126     * @see WritableDirectoryException#check(String)
127     * @see SameSourceAndTargetException#check(FileNode, String)
128     */
129    @LinkJavaSource(handle="CopyFiles")
130    public static int copyRecursive(
131            final FileNode          directory,
132            final FileNodeFilter    fileFilter,
133            final FileNodeFilter    dirFilter,
134            final String            targetDirectory,
135            final Appendable        a
136        )
137        throws  IOException, SameSourceAndTargetException,
138                InvalidPathException, NoSuchFileException
139    {
140        DirExpectedException.check(directory);
141        WritableDirectoryException.check(targetDirectory);
142        SameSourceAndTargetException.check(directory, targetDirectory);
143
144        final String td = targetDirectory.endsWith(File.separator)
145            ? targetDirectory 
146            : targetDirectory + File.separator;
147
148        return CopyFiles.RECURSIVE(directory, fileFilter, dirFilter, td, a);
149    }
150
151    /**
152     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_DEL_DESC>
153     * @param directory <EMBED CLASS='external-html' DATA-FILE-ID=FT_DEL_DIRECTORY>
154     * @param filter    <EMBED CLASS='external-html' DATA-FILE-ID=FT_DEL_FILTER>
155     * @param a         An output log, for debugging &amp; logging informational messages.
156     *                  This parameter may be null, and if so, it will be silently ignored.
157     *                  <EMBED CLASS='external-html' DATA-FILE-ID=APPENDABLE>
158     * @return          <EMBED CLASS='external-html' DATA-FILE-ID=FT_DEL_RETURNS>
159     * 
160     * @throws DirExpectedException If you pass a "file" instance of {@code class FileNode} to
161     * parameter {@code 'directory'}.
162     *
163     * @throws IOException For any IO file-system errors.
164     *
165     * @see #deleteFilesRecursive(FileNode, FileNodeFilter, FileNodeFilter, Appendable)
166     * @see FileNode#getDirContentsFiles(RTC)
167     * @see FileNode#getJavaIOFile()
168     * @see DirExpectedException#check(FileNode)
169     */
170    @LinkJavaSource(handle="DeleteFiles")
171    public static int deleteFiles(
172            final FileNode          directory,
173            final FileNodeFilter    filter,
174            final Appendable        a
175        )
176        throws IOException
177    {
178        DirExpectedException.check(directory);
179        return DeleteFiles.DELETE(directory, filter, a);
180    }
181
182    /**
183     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_DELREC_DESC>
184     * @param directory     <EMBED CLASS='external-html' DATA-FILE-ID=FT_DELREC_DIRECTORY>
185     * @param fileFilter    <EMBED CLASS='external-html' DATA-FILE-ID=FT_DELREC_FILE_FILT>
186     * @param dirFilter     <EMBED CLASS='external-html' DATA-FILE-ID=FT_DELREC_DIR_FILT>
187     * @param a             An output log, for debugging &amp; logging informational messages.
188     *                      This parameter may be null, and if so, it will be silently ignored.
189     * @return              <EMBED CLASS='external-html' DATA-FILE-ID=FT_DELREC_RET>
190     * 
191     * @throws DirExpectedException If you pass a "file" instance of {@code class FileNode} to
192     * parameter {@code 'directory'}
193     * 
194     * @throws IOException For any IO file-system errors.
195     * 
196     * @see #deleteFiles(FileNode, FileNodeFilter, Appendable)
197     * @see FileNode#getDirContentsDirs(RTC)
198     * @see FileNode#getJavaIOFile()
199     * @see DirExpectedException#check(FileNode)
200     */
201    @LinkJavaSource(handle="DeleteFiles")
202    public static int deleteFilesRecursive(
203            FileNode directory, FileNodeFilter fileFilter, FileNodeFilter dirFilter,
204            Appendable a
205        )
206        throws IOException
207    {
208        DirExpectedException.check(directory);
209        return DeleteFiles.RECURSIVE(directory, fileFilter, dirFilter, a);
210    }
211
212    /**
213     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_DESC>
214     * @param directory         <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_DIRECTORY>
215     * @param targetDirectory   <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_TARGET_DIR>
216     * @param filter            <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_FILTER>
217     * @param a                 An output log, for debugging &amp; logging informational messages.
218     *                          This parameter may be null, and if so, it will be silently ignored.
219     *                          <EMBED CLASS='external-html' DATA-FILE-ID=APPENDABLE>
220     * @return                  The number of files that were moved.
221     *
222     * @throws DirExpectedException If you pass a "file" instance of {@code class FileNode} to
223     * parameter {@code 'directory.'}
224     * 
225     * @throws WritableDirectoryException If the target-directory is not available to Java for
226     * moving.
227     * 
228     * @throws java.nio.file.NoSuchFileException
229     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_NO_SUCH_F_EX>
230     * 
231     * @throws java.nio.file.InvalidPathException
232     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_INVALID_P_EX>
233     * 
234     * @throws SameSourceAndTargetException
235     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_SAME_SRC_T_EX>
236     * 
237     * @throws IOException For any IO file-system errors.
238     * 
239     * @see #moveRecursive(FileNode, FileNodeFilter, FileNodeFilter, String, Appendable)
240     * @see DirExpectedException#check(FileNode)
241     * @see WritableDirectoryException#check(String)
242     * @see SameSourceAndTargetException#check(FileNode, String)
243     */
244    @LinkJavaSource(handle="MoveFiles")
245    public static int move(
246            final FileNode          directory,
247            final FileNodeFilter    filter,
248            final String            targetDirectory,
249            final Appendable        a
250        ) 
251        throws  IOException, SameSourceAndTargetException,
252                InvalidPathException, NoSuchFileException
253    {
254        DirExpectedException.check(directory);
255        WritableDirectoryException.check(targetDirectory);
256        SameSourceAndTargetException.check(directory, targetDirectory);
257
258        final String td = targetDirectory.endsWith(File.separator)
259            ? targetDirectory 
260            : targetDirectory + File.separator;
261
262        return MoveFiles.MOVE(directory, filter, td, a);
263    }
264
265    /**
266     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_DESC>
267     * @param directory         <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_DIRECTORY>
268     * @param targetDirectory   <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_TARGET_DIR>
269     * @param fileFilter        <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_DIR_FILT>
270     * @param dirFilter         <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_FILE_FILT>
271     * @param a                 An output log, for debugging &amp; logging informational messages.
272     *                          This parameter may be null, and if so, it will be silently ignored.
273     * @return                  <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_RET>
274     * 
275     * @throws DirExpectedException If you pass a "file" instance of {@code class FileNode} to
276     * parameter {@code 'directory.'}
277     * 
278     * @throws WritableDirectoryException 
279     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MVREC_W_DIR_EX>
280     * 
281     * @throws java.nio.file.NoSuchFileException
282     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_NO_SUCH_F_EX>
283     * 
284     * @throws java.nio.file.InvalidPathException
285     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_INVALID_P_EX>
286     * 
287     * @throws SameSourceAndTargetException
288     * <EMBED CLASS='external-html' DATA-FILE-ID=FT_MV_SAME_SRC_T_EX>
289     * 
290     * @throws IOException For any IO filesystem errors.
291     * 
292     * @see #move(FileNode, FileNodeFilter, String, Appendable)
293     * @see FileNode#getDirContentsDirs(RTC)
294     * @see DirExpectedException#check(FileNode)
295     * @see WritableDirectoryException#check(String)
296     * @see SameSourceAndTargetException#check(FileNode, String)
297     */
298    @LinkJavaSource(handle="MoveFiles")
299    public static int moveRecursive(
300            FileNode directory, FileNodeFilter fileFilter, FileNodeFilter dirFilter,
301            String targetDirectory, Appendable a
302        )
303        throws  IOException, SameSourceAndTargetException,
304                InvalidPathException, NoSuchFileException
305    {
306        DirExpectedException.check(directory);
307        WritableDirectoryException.check(targetDirectory);
308        SameSourceAndTargetException.check(directory, targetDirectory);
309
310        final String td = targetDirectory.endsWith(File.separator)
311            ? targetDirectory 
312            : targetDirectory + File.separator;
313
314        return MoveFiles.RECURSIVE(directory, fileFilter, dirFilter, td, a);
315    }
316}