1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.file;
19
20 import java.io.IOException;
21 import java.math.BigInteger;
22 import java.nio.file.FileVisitResult;
23 import java.nio.file.Files;
24 import java.nio.file.Path;
25 import java.nio.file.attribute.BasicFileAttributes;
26 import java.util.Objects;
27 import java.util.function.UnaryOperator;
28
29 import org.apache.commons.io.file.Counters.PathCounters;
30 import org.apache.commons.io.filefilter.IOFileFilter;
31 import org.apache.commons.io.filefilter.TrueFileFilter;
32 import org.apache.commons.io.function.IOBiFunction;
33
34
35
36
37
38
39 public class CountingPathVisitor extends SimplePathVisitor {
40
41
42
43
44
45
46
47
48 public abstract static class AbstractBuilder<T, B extends AbstractBuilder<T, B>> extends SimplePathVisitor.AbstractBuilder<T, B> {
49
50 private PathCounters pathCounters = defaultPathCounters();
51 private PathFilter fileFilter = defaultFileFilter();
52 private PathFilter directoryFilter = defaultDirectoryFilter();
53 private UnaryOperator<Path> directoryPostTransformer = defaultDirectoryTransformer();
54
55
56
57
58 public AbstractBuilder() {
59
60 }
61
62 PathFilter getDirectoryFilter() {
63 return directoryFilter;
64 }
65
66 UnaryOperator<Path> getDirectoryPostTransformer() {
67 return directoryPostTransformer;
68 }
69
70 PathFilter getFileFilter() {
71 return fileFilter;
72 }
73
74 PathCounters getPathCounters() {
75 return pathCounters;
76 }
77
78
79
80
81
82
83
84 public B setDirectoryFilter(final PathFilter directoryFilter) {
85 this.directoryFilter = directoryFilter != null ? directoryFilter : defaultDirectoryFilter();
86 return asThis();
87 }
88
89
90
91
92
93
94
95 public B setDirectoryPostTransformer(final UnaryOperator<Path> directoryTransformer) {
96 this.directoryPostTransformer = directoryTransformer != null ? directoryTransformer : defaultDirectoryTransformer();
97 return asThis();
98 }
99
100
101
102
103
104
105
106 public B setFileFilter(final PathFilter fileFilter) {
107 this.fileFilter = fileFilter != null ? fileFilter : defaultFileFilter();
108 return asThis();
109 }
110
111
112
113
114
115
116
117 public B setPathCounters(final PathCounters pathCounters) {
118 this.pathCounters = pathCounters != null ? pathCounters : defaultPathCounters();
119 return asThis();
120 }
121 }
122
123
124
125
126
127
128 public static class Builder extends AbstractBuilder<CountingPathVisitor, Builder> {
129
130
131
132
133 public Builder() {
134
135 }
136
137 @Override
138 public CountingPathVisitor get() {
139 return new CountingPathVisitor(this);
140 }
141 }
142
143 static final String[] EMPTY_STRING_ARRAY = {};
144
145 static IOFileFilter defaultDirectoryFilter() {
146 return TrueFileFilter.INSTANCE;
147 }
148
149 static UnaryOperator<Path> defaultDirectoryTransformer() {
150 return UnaryOperator.identity();
151 }
152
153 static IOFileFilter defaultFileFilter() {
154 return TrueFileFilter.INSTANCE;
155 }
156
157 static PathCounters defaultPathCounters() {
158 return Counters.longPathCounters();
159 }
160
161
162
163
164
165
166 public static CountingPathVisitor withBigIntegerCounters() {
167 return new Builder().setPathCounters(Counters.bigIntegerPathCounters()).get();
168 }
169
170
171
172
173
174
175 public static CountingPathVisitor withLongCounters() {
176 return new Builder().setPathCounters(Counters.longPathCounters()).get();
177 }
178
179 private final PathCounters pathCounters;
180 private final PathFilter fileFilter;
181 private final PathFilter directoryFilter;
182 private final UnaryOperator<Path> directoryPostTransformer;
183
184 CountingPathVisitor(final AbstractBuilder<?, ?> builder) {
185 super(builder);
186 this.pathCounters = builder.getPathCounters();
187 this.fileFilter = builder.getFileFilter();
188 this.directoryFilter = builder.getDirectoryFilter();
189 this.directoryPostTransformer = builder.getDirectoryPostTransformer();
190 }
191
192
193
194
195
196
197
198 public CountingPathVisitor(final PathCounters pathCounters) {
199 this(new Builder().setPathCounters(pathCounters));
200 }
201
202
203
204
205
206
207
208
209
210
211 public CountingPathVisitor(final PathCounters pathCounters, final PathFilter fileFilter, final PathFilter directoryFilter) {
212 this.pathCounters = Objects.requireNonNull(pathCounters, "pathCounters");
213 this.fileFilter = Objects.requireNonNull(fileFilter, "fileFilter");
214 this.directoryFilter = Objects.requireNonNull(directoryFilter, "directoryFilter");
215 this.directoryPostTransformer = UnaryOperator.identity();
216 }
217
218
219
220
221
222
223
224
225
226
227
228 @Deprecated
229 public CountingPathVisitor(final PathCounters pathCounters, final PathFilter fileFilter, final PathFilter directoryFilter,
230 final IOBiFunction<Path, IOException, FileVisitResult> visitFileFailed) {
231 super(visitFileFailed);
232 this.pathCounters = Objects.requireNonNull(pathCounters, "pathCounters");
233 this.fileFilter = Objects.requireNonNull(fileFilter, "fileFilter");
234 this.directoryFilter = Objects.requireNonNull(directoryFilter, "directoryFilter");
235 this.directoryPostTransformer = UnaryOperator.identity();
236 }
237
238
239
240
241
242
243
244
245
246 protected boolean accept(final Path file, final BasicFileAttributes attributes) {
247
248 return Files.exists(file) && fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE;
249 }
250
251 @Override
252 public boolean equals(final Object obj) {
253 if (this == obj) {
254 return true;
255 }
256 if (!(obj instanceof CountingPathVisitor)) {
257 return false;
258 }
259 final CountingPathVisitor other = (CountingPathVisitor) obj;
260 return Objects.equals(pathCounters, other.pathCounters);
261 }
262
263
264
265
266
267
268 public PathCounters getPathCounters() {
269 return pathCounters;
270 }
271
272 @Override
273 public int hashCode() {
274 return Objects.hash(pathCounters);
275 }
276
277 @Override
278 public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
279 updateDirCounter(directoryPostTransformer.apply(dir), exc);
280 return FileVisitResult.CONTINUE;
281 }
282
283 @Override
284 public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException {
285 final FileVisitResult accept = directoryFilter.accept(dir, attributes);
286 return accept != FileVisitResult.CONTINUE ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
287 }
288
289 @Override
290 public String toString() {
291 return pathCounters.toString();
292 }
293
294
295
296
297
298
299
300
301 protected void updateDirCounter(final Path dir, final IOException exc) {
302 pathCounters.getDirectoryCounter().increment();
303 }
304
305
306
307
308
309
310
311 protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) {
312 pathCounters.getFileCounter().increment();
313 pathCounters.getByteCounter().add(attributes.size());
314 }
315
316 @Override
317 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException {
318 if (accept(file, attributes)) {
319 updateFileCounters(file, attributes);
320 }
321 return FileVisitResult.CONTINUE;
322 }
323
324 }