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