View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.io.filefilter;
18  
19  import java.io.File;
20  import java.io.FileFilter;
21  import java.io.FilenameFilter;
22  import java.io.IOException;
23  import java.nio.file.FileVisitResult;
24  import java.nio.file.Path;
25  import java.nio.file.attribute.BasicFileAttributes;
26  import java.util.List;
27  import java.util.Objects;
28  
29  import org.apache.commons.io.file.PathFilter;
30  import org.apache.commons.io.file.PathVisitor;
31  import org.apache.commons.io.function.IOSupplier;
32  
33  /**
34   * Abstracts the implementation of the {@link FileFilter} (IO), {@link FilenameFilter} (IO), {@link PathFilter} (NIO)
35   * interfaces via our own {@link IOFileFilter} interface.
36   * <p>
37   * Note that a subclass MUST override one of the {@code accept} methods, otherwise that subclass will infinitely loop.
38   * </p>
39   *
40   * @since 1.0
41   */
42  public abstract class AbstractFileFilter implements IOFileFilter, PathVisitor {
43  
44      static FileVisitResult toDefaultFileVisitResult(final boolean accept) {
45          return accept ? FileVisitResult.CONTINUE : FileVisitResult.TERMINATE;
46      }
47  
48      /**
49       * What to do when this filter accepts.
50       */
51      private final FileVisitResult onAccept;
52  
53      /**
54       * What to do when this filter rejects.
55       */
56      private final FileVisitResult onReject;
57  
58      /**
59       * Constructs a new instance.
60       */
61      public AbstractFileFilter() {
62          this(FileVisitResult.CONTINUE, FileVisitResult.TERMINATE);
63      }
64  
65      /**
66       * Constructs a new instance.
67       *
68       * @param onAccept What to do on acceptance.
69       * @param onReject What to do on rejection.
70       * @since 2.12.0.
71       */
72      protected AbstractFileFilter(final FileVisitResult onAccept, final FileVisitResult onReject) {
73          this.onAccept = onAccept;
74          this.onReject = onReject;
75      }
76  
77      /**
78       * Tests to see if the File should be accepted by this filter.
79       *
80       * @param file the File to check.
81       * @return true if this file matches the test.
82       */
83      @Override
84      public boolean accept(final File file) {
85          Objects.requireNonNull(file, "file");
86          return accept(file.getParentFile(), file.getName());
87      }
88  
89      /**
90       * Tests to see if the File should be accepted by this filter.
91       *
92       * @param dir the directory File to check.
93       * @param name the file name within the directory to check.
94       * @return true if this file matches the test.
95       */
96      @Override
97      public boolean accept(final File dir, final String name) {
98          Objects.requireNonNull(name, "name");
99          return accept(new File(dir, name));
100     }
101 
102     void append(final List<?> list, final StringBuilder buffer) {
103         for (int i = 0; i < list.size(); i++) {
104             if (i > 0) {
105                 buffer.append(",");
106             }
107             buffer.append(list.get(i));
108         }
109     }
110 
111     void append(final Object[] array, final StringBuilder buffer) {
112         for (int i = 0; i < array.length; i++) {
113             if (i > 0) {
114                 buffer.append(",");
115             }
116             buffer.append(array[i]);
117         }
118     }
119 
120     FileVisitResult get(final IOSupplier<FileVisitResult> supplier) {
121         try {
122             return supplier.get();
123         } catch (final IOException e) {
124             return handle(e);
125         }
126     }
127 
128     /**
129      * Handles exceptions caught while accepting.
130      *
131      * @param t the caught Throwable.
132      * @return the given Throwable.
133      * @since 2.9.0
134      */
135     protected FileVisitResult handle(final Throwable t) {
136         return FileVisitResult.TERMINATE;
137     }
138 
139     boolean isDirectory(final File file) {
140         return file != null && file.isDirectory();
141     }
142 
143     boolean isFile(final File file) {
144         return file != null && file.isFile();
145     }
146 
147     @Override
148     public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
149         return FileVisitResult.CONTINUE;
150     }
151 
152     @Override
153     public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException {
154         return accept(dir, attributes);
155     }
156 
157     /**
158      * Converts a boolean into a FileVisitResult.
159      *
160      * @param accept accepted or rejected.
161      * @return a FileVisitResult.
162      */
163     FileVisitResult toFileVisitResult(final boolean accept) {
164         return accept ? onAccept : onReject;
165     }
166 
167     /**
168      * Provides a String representation of this file filter.
169      *
170      * @return a String representation.
171      */
172     @Override
173     public String toString() {
174         return getClass().getSimpleName();
175     }
176 
177     @Override
178     public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException {
179         return accept(file, attributes);
180     }
181 
182     @Override
183     public FileVisitResult visitFileFailed(final Path file, final IOException exc) throws IOException {
184         return FileVisitResult.CONTINUE;
185     }
186 
187 }