Author: scolebourne Date: Sat Oct 14 07:26:28 2006 New Revision: 463942 URL: http://svn.apache.org/viewvc?view=rev&rev=463942 Log: Add constructor to take directory and file filters separately
Modified: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/DirectoryWalker.java jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/DirectoryWalkerTestCase.java Modified: jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/DirectoryWalker.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/DirectoryWalker.java?view=diff&rev=463942&r1=463941&r2=463942 ============================================================================== --- jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/DirectoryWalker.java (original) +++ jakarta/commons/proper/io/trunk/src/java/org/apache/commons/io/DirectoryWalker.java Sat Oct 14 07:26:28 2006 @@ -21,6 +21,10 @@ import java.io.IOException; import java.util.Collection; +import org.apache.commons.io.filefilter.FileFilterUtils; +import org.apache.commons.io.filefilter.IOFileFilter; +import org.apache.commons.io.filefilter.TrueFileFilter; + /** * Abstract class that walks through a directory hierarchy and provides * subclasses with convenient hooks to add specific behaviour. @@ -80,14 +84,28 @@ * <a name="filter"></a> * <h3>2. Filter Example</h3> * - * If you wanted all directories which are not hidden - * and files which end in ".txt" - you could build a composite filter - * using the filter implementations in the Commons IO - * <a href="filefilter/package-summary.html">filefilter</a> package - * in the following way: - * + * Choosing which directories and files to process can be a key aspect + * of using this class. This information can be setup in three ways, + * via three different constructors. + * <p> + * The first option is to visit all directories and files. + * This is achieved via the no-args constructor. + * <p> + * The second constructor option is to supply a single [EMAIL PROTECTED] FileFilter} + * that describes the files and directories to visit. Care must be taken + * with this option as the same filter is used for both directories + * and files. + * <p> + * For example, if you wanted all directories which are not hidden + * and files which end in ".txt": * <pre> - * + * public class FooDirectoryWalker extends DirectoryWalker { + * public FooDirectoryWalker(FileFilter filter) { + * super(filter, -1); + * } + * } + * + * // Build up the filters and create the walker * // Create a filter for Non-hidden directories * IOFileFilter fooDirFilter = * FileFilterUtils.andFileFilter(FileFilterUtils.directoryFileFilter, @@ -103,9 +121,32 @@ * FileFilterUtils.orFileFilter(fooDirFilter, fooFileFilter); * * // Use the filter to construct a DirectoryWalker implementation - * FooDirectoryWalker walker = new FooDirectoryWalker(fooFilter, -1); - * + * FooDirectoryWalker walker = new FooDirectoryWalker(fooFilter); * </pre> + * <p> + * The third constructor option is to specify separate filters, one for + * directories and one for files. These are combined internally to form + * the correct <code>FileFilter</code>, something which is very easy to + * get wrong when attempted manually, particularly when trying to + * express constructs like 'any file in directories named docs'. + * <p> + * For example, if you wanted all directories which are not hidden + * and files which end in ".txt": + * <pre> + * public class FooDirectoryWalker extends DirectoryWalker { + * public FooDirectoryWalker(IOFileFilter dirFilter, IOFileFilter fileFilter) { + * super(dirFilter, fileFilter, -1); + * } + * } + * + * // Use the filters to construct the walker + * FooDirectoryWalker walker = new FooDirectoryWalker( + * HiddenFileFilter.VISIBLE, + * FileFilterUtils.suffixFileFilter(".txt"), + * ); + * <pre> + * This is much simpler than the previous example, and is why it is the preferred + * option for filtering. * * <a name="cancel"></a> * <h3>3. Cancellation</h3> @@ -145,8 +186,8 @@ * * This example provides a <code>cancel()</code> method for external processes to * indcate that processing must stop. Calling this method sets a - * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930"> - * volatile</a> flag to (hopefully) ensure it will work properly in + * <a href="http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#36930">volatile</a> + * flag to (hopefully) ensure it will work properly in * a multi-threaded environment. In this implementation the flag is checked in two * of the lifecycle methods using a convenience <code>checkIfCancelled()</code> method * which throws a [EMAIL PROTECTED] CancelException} if cancellation has been requested. @@ -237,13 +278,45 @@ /** * Construct an instance with a filter and limit the <i>depth</i> navigated to. + * <p> + * The filter controls which files and directories will be navigated to as + * part of the walk. The [EMAIL PROTECTED] FileFilterUtils} class is useful for combining + * various filters together. A <code>null</code> filter means that no + * filtering should occur and all files and directories will be visited. * - * @param filter the filter to limit the navigation/results, may be null + * @param filter the filter to apply, null means visit all files * @param depthLimit controls how <i>deep</i> the hierarchy is * navigated to (less than 0 means unlimited) */ protected DirectoryWalker(FileFilter filter, int depthLimit) { this.filter = filter; + this.depthLimit = depthLimit; + } + + /** + * Construct an instance with a directory and a file filter and an optional + * limit on the <i>depth</i> navigated to. + * <p> + * The filters control which files and directories will be navigated to as part + * of the walk. This constructor uses [EMAIL PROTECTED] FileFilterUtils#makeDirectoryOnly()} + * and [EMAIL PROTECTED] FileFilterUtils#makeFileOnly()} internally to combine the filters. + * A <code>null</code> filter means that no filtering should occur. + * + * @param directoryFilter the filter to apply to directories, null means visit all directories + * @param fileFilter the filter to apply to files, null means visit all files + * @param depthLimit controls how <i>deep</i> the hierarchy is + * navigated to (less than 0 means unlimited) + */ + protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter, int depthLimit) { + if (directoryFilter == null && fileFilter == null) { + this.filter = null; + } else { + directoryFilter = (directoryFilter != null ? directoryFilter : TrueFileFilter.TRUE); + fileFilter = (fileFilter != null ? fileFilter : TrueFileFilter.TRUE); + directoryFilter = FileFilterUtils.makeDirectoryOnly(directoryFilter); + fileFilter = FileFilterUtils.makeFileOnly(fileFilter); + this.filter = FileFilterUtils.orFileFilter(directoryFilter, fileFilter); + } this.depthLimit = depthLimit; } Modified: jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/DirectoryWalkerTestCase.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/DirectoryWalkerTestCase.java?view=diff&rev=463942&r1=463941&r2=463942 ============================================================================== --- jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/DirectoryWalkerTestCase.java (original) +++ jakarta/commons/proper/io/trunk/src/test/org/apache/commons/io/DirectoryWalkerTestCase.java Sat Oct 14 07:26:28 2006 @@ -19,6 +19,7 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; +import java.util.Iterator; import java.util.List; import java.util.ArrayList; import java.util.Collection; @@ -146,6 +147,50 @@ } /** + * Test separate dir and file filters + */ + public void testFilterDirAndFile1() { + List results = new TestFileFinder(dirsFilter, iofilesFilter, -1).find(javaDir); + assertEquals("[DirAndFile1] Result Size", (1 + dirs.length + ioFiles.length), results.size()); + assertTrue("[DirAndFile1] Start Dir", results.contains(javaDir)); + checkContainsFiles("[DirAndFile1] Dir", dirs, results); + checkContainsFiles("[DirAndFile1] File", ioFiles, results); + } + + /** + * Test separate dir and file filters + */ + public void testFilterDirAndFile2() { + List results = new TestFileFinder((IOFileFilter) null, (IOFileFilter) null, -1).find(javaDir); + assertTrue("[DirAndFile2] Result Size", results.size() > (1 + dirs.length + ioFiles.length)); + assertTrue("[DirAndFile2] Start Dir", results.contains(javaDir)); + checkContainsFiles("[DirAndFile2] Dir", dirs, results); + checkContainsFiles("[DirAndFile2] File", ioFiles, results); + } + + /** + * Test separate dir and file filters + */ + public void testFilterDirAndFile3() { + List results = new TestFileFinder(dirsFilter, (IOFileFilter) null, -1).find(javaDir); + List resultDirs = directoriesOnly(results); + assertEquals("[DirAndFile3] Result Size", (1 + dirs.length), resultDirs.size()); + assertTrue("[DirAndFile3] Start Dir", results.contains(javaDir)); + checkContainsFiles("[DirAndFile3] Dir", dirs, resultDirs); + } + + /** + * Test separate dir and file filters + */ + public void testFilterDirAndFile4() { + List results = new TestFileFinder((IOFileFilter) null, iofilesFilter, -1).find(javaDir); + List resultFiles = filesOnly(results); + assertEquals("[DirAndFile4] Result Size", ioFiles.length, resultFiles.size()); + assertTrue("[DirAndFile4] Start Dir", results.contains(javaDir)); + checkContainsFiles("[DirAndFile4] File", ioFiles, resultFiles); + } + + /** * Test Limiting to current directory */ public void testLimitToCurrent() { @@ -195,6 +240,34 @@ } /** + * Extract the directories. + */ + private List directoriesOnly(Collection results) { + List list = new ArrayList(results.size()); + for (Iterator it = results.iterator(); it.hasNext(); ) { + File file = (File) it.next(); + if (file.isDirectory()) { + list.add(file); + } + } + return list; + } + + /** + * Extract the files. + */ + private List filesOnly(Collection results) { + List list = new ArrayList(results.size()); + for (Iterator it = results.iterator(); it.hasNext(); ) { + File file = (File) it.next(); + if (file.isFile()) { + list.add(file); + } + } + return list; + } + + /** * Create an name filter containg the names of the files * in the array. */ @@ -257,6 +330,10 @@ protected TestFileFinder(FileFilter filter, int depthLimit) { super(filter, depthLimit); + } + + protected TestFileFinder(IOFileFilter dirFilter, IOFileFilter fileFilter, int depthLimit) { + super(dirFilter, fileFilter, depthLimit); } /** find files. */ --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]