• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *      http://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 
18 package org.apache.commons.io.file;
19 
20 import java.math.BigInteger;
21 import java.util.Objects;
22 
23 /**
24  * Provides counters for files, directories, and sizes, as a visit proceeds.
25  *
26  * @since 2.7
27  */
28 public class Counters {
29 
30     /**
31      * Counts files, directories, and sizes, as a visit proceeds.
32      */
33     private static class AbstractPathCounters implements PathCounters {
34 
35         private final Counter byteCounter;
36         private final Counter directoryCounter;
37         private final Counter fileCounter;
38 
39         /**
40          * Constructs a new instance.
41          *
42          * @param byteCounter the byte counter.
43          * @param directoryCounter the directory counter.
44          * @param fileCounter the file counter.
45          */
AbstractPathCounters(final Counter byteCounter, final Counter directoryCounter, final Counter fileCounter)46         protected AbstractPathCounters(final Counter byteCounter, final Counter directoryCounter, final Counter fileCounter) {
47             this.byteCounter = byteCounter;
48             this.directoryCounter = directoryCounter;
49             this.fileCounter = fileCounter;
50         }
51 
52         @Override
equals(final Object obj)53         public boolean equals(final Object obj) {
54             if (this == obj) {
55                 return true;
56             }
57             if (!(obj instanceof AbstractPathCounters)) {
58                 return false;
59             }
60             final AbstractPathCounters other = (AbstractPathCounters) obj;
61             return Objects.equals(byteCounter, other.byteCounter)
62                 && Objects.equals(directoryCounter, other.directoryCounter)
63                 && Objects.equals(fileCounter, other.fileCounter);
64         }
65 
66         @Override
getByteCounter()67         public Counter getByteCounter() {
68             return byteCounter;
69         }
70 
71         @Override
getDirectoryCounter()72         public Counter getDirectoryCounter() {
73             return directoryCounter;
74         }
75 
76         /**
77          * Gets the count of visited files.
78          *
79          * @return the byte count of visited files.
80          */
81         @Override
getFileCounter()82         public Counter getFileCounter() {
83             return this.fileCounter;
84         }
85 
86         @Override
hashCode()87         public int hashCode() {
88             return Objects.hash(byteCounter, directoryCounter, fileCounter);
89         }
90 
91         @Override
reset()92         public void reset() {
93             byteCounter.reset();
94             directoryCounter.reset();
95             fileCounter.reset();
96         }
97 
98         @Override
toString()99         public String toString() {
100             return String.format("%,d files, %,d directories, %,d bytes", Long.valueOf(fileCounter.get()),
101                 Long.valueOf(directoryCounter.get()), Long.valueOf(byteCounter.get()));
102         }
103 
104     }
105 
106     /**
107      * Counts using a {@link BigInteger} number.
108      */
109     private static final class BigIntegerCounter implements Counter {
110 
111         private BigInteger value = BigInteger.ZERO;
112 
113         @Override
add(final long val)114         public void add(final long val) {
115             value = value.add(BigInteger.valueOf(val));
116 
117         }
118 
119         @Override
equals(final Object obj)120         public boolean equals(final Object obj) {
121             if (this == obj) {
122                 return true;
123             }
124             if (!(obj instanceof Counter)) {
125                 return false;
126             }
127             final Counter other = (Counter) obj;
128             return Objects.equals(value, other.getBigInteger());
129         }
130 
131         @Override
get()132         public long get() {
133             return value.longValueExact();
134         }
135 
136         @Override
getBigInteger()137         public BigInteger getBigInteger() {
138             return value;
139         }
140 
141         @Override
getLong()142         public Long getLong() {
143             return Long.valueOf(value.longValueExact());
144         }
145 
146         @Override
hashCode()147         public int hashCode() {
148             return Objects.hash(value);
149         }
150 
151         @Override
increment()152         public void increment() {
153             value = value.add(BigInteger.ONE);
154         }
155 
156         @Override
reset()157         public void reset() {
158             value = BigInteger.ZERO;
159         }
160 
161         @Override
toString()162         public String toString() {
163             return value.toString();
164         }
165     }
166 
167     /**
168      * Counts files, directories, and sizes, as a visit proceeds, using BigInteger numbers.
169      */
170     private final static class BigIntegerPathCounters extends AbstractPathCounters {
171 
172         /**
173          * Constructs a new initialized instance.
174          */
BigIntegerPathCounters()175         protected BigIntegerPathCounters() {
176             super(Counters.bigIntegerCounter(), Counters.bigIntegerCounter(), Counters.bigIntegerCounter());
177         }
178 
179     }
180 
181     /**
182      * Counts using a number.
183      */
184     public interface Counter {
185 
186         /**
187          * Adds the given number to this counter.
188          *
189          * @param val the value to add.
190          */
add(long val)191         void add(long val);
192 
193         /**
194          * Gets the counter as a long.
195          *
196          * @return the counter as a long.
197          */
get()198         long get();
199 
200         /**
201          * Gets the counter as a BigInteger.
202          *
203          * @return the counter as a BigInteger.
204          */
getBigInteger()205         BigInteger getBigInteger();
206 
207         /**
208          * Gets the counter as a Long.
209          *
210          * @return the counter as a Long.
211          */
getLong()212         Long getLong();
213 
214         /**
215          * Adds one to this counter.
216          */
increment()217         void increment();
218 
219         /**
220          * Resets this count to 0.
221          */
reset()222         default void reset() {
223             // binary compat, do nothing
224         }
225 
226     }
227 
228     /**
229      * Counts using a {@code long} number.
230      */
231     private final static class LongCounter implements Counter {
232 
233         private long value;
234 
235         @Override
add(final long add)236         public void add(final long add) {
237             value += add;
238 
239         }
240 
241         @Override
equals(final Object obj)242         public boolean equals(final Object obj) {
243             if (this == obj) {
244                 return true;
245             }
246             if (!(obj instanceof Counter)) {
247                 return false;
248             }
249             final Counter other = (Counter) obj;
250             return value == other.get();
251         }
252 
253         @Override
get()254         public long get() {
255             return value;
256         }
257 
258         @Override
getBigInteger()259         public BigInteger getBigInteger() {
260             return BigInteger.valueOf(value);
261         }
262 
263         @Override
getLong()264         public Long getLong() {
265             return Long.valueOf(value);
266         }
267 
268         @Override
hashCode()269         public int hashCode() {
270             return Objects.hash(value);
271         }
272 
273         @Override
increment()274         public void increment() {
275             value++;
276         }
277 
278         @Override
reset()279         public void reset() {
280             value = 0L;
281         }
282 
283         @Override
toString()284         public String toString() {
285             return Long.toString(value);
286         }
287     }
288 
289     /**
290      * Counts files, directories, and sizes, as a visit proceeds, using long numbers.
291      */
292     private final static class LongPathCounters extends AbstractPathCounters {
293 
294         /**
295          * Constructs a new initialized instance.
296          */
LongPathCounters()297         protected LongPathCounters() {
298             super(Counters.longCounter(), Counters.longCounter(), Counters.longCounter());
299         }
300 
301     }
302 
303     /**
304      * Counts nothing.
305      */
306     private final static class NoopCounter implements Counter {
307 
308         static final NoopCounter INSTANCE = new NoopCounter();
309 
310         @Override
add(final long add)311         public void add(final long add) {
312             // noop
313         }
314 
315         @Override
get()316         public long get() {
317             return 0;
318         }
319 
320         @Override
getBigInteger()321         public BigInteger getBigInteger() {
322             return BigInteger.ZERO;
323         }
324 
325         @Override
getLong()326         public Long getLong() {
327             return 0L;
328         }
329 
330         @Override
increment()331         public void increment() {
332             // noop
333         }
334 
335         /**
336          * Returns {@code "0"}, always.
337          *
338          * @return {@code "0"}, always.
339          * @since 2.12.0
340          */
341         @Override
toString()342         public String toString() {
343             return "0";
344         }
345 
346     }
347 
348     /**
349      * Counts nothing.
350      */
351     private static final class NoopPathCounters extends AbstractPathCounters {
352 
353         static final NoopPathCounters INSTANCE = new NoopPathCounters();
354 
355         /**
356          * Constructs a new initialized instance.
357          */
NoopPathCounters()358         private NoopPathCounters() {
359             super(Counters.noopCounter(), Counters.noopCounter(), Counters.noopCounter());
360         }
361 
362     }
363 
364     /**
365      * Counts files, directories, and sizes, as a visit proceeds.
366      */
367     public interface PathCounters {
368 
369         /**
370          * Gets the byte counter.
371          *
372          * @return the byte counter.
373          */
getByteCounter()374         Counter getByteCounter();
375 
376         /**
377          * Gets the directory counter.
378          *
379          * @return the directory counter.
380          */
getDirectoryCounter()381         Counter getDirectoryCounter();
382 
383         /**
384          * Gets the file counter.
385          *
386          * @return the file counter.
387          */
getFileCounter()388         Counter getFileCounter();
389 
390         /**
391          * Resets the counts to 0.
392          */
reset()393         default void reset() {
394             // binary compat, do nothing
395         }
396 
397     }
398 
399     /**
400      * Returns a new BigInteger Counter.
401      *
402      * @return a new BigInteger Counter.
403      */
bigIntegerCounter()404     public static Counter bigIntegerCounter() {
405         return new BigIntegerCounter();
406     }
407 
408     /**
409      * Returns a new BigInteger PathCounters.
410      *
411      * @return a new BigInteger PathCounters.
412      */
bigIntegerPathCounters()413     public static PathCounters bigIntegerPathCounters() {
414         return new BigIntegerPathCounters();
415     }
416 
417     /**
418      * Returns a new long Counter.
419      *
420      * @return a new long Counter.
421      */
longCounter()422     public static Counter longCounter() {
423         return new LongCounter();
424     }
425 
426     /**
427      * Returns a new BigInteger PathCounters.
428      *
429      * @return a new BigInteger PathCounters.
430      */
longPathCounters()431     public static PathCounters longPathCounters() {
432         return new LongPathCounters();
433     }
434 
435     /**
436      * Returns the no-op Counter.
437      *
438      * @return the no-op Counter.
439      * @since 2.9.0
440      */
noopCounter()441     public static Counter noopCounter() {
442         return NoopCounter.INSTANCE;
443     }
444 
445     /**
446      * Returns the no-op PathCounters.
447      *
448      * @return the no-op PathCounters.
449      * @since 2.9.0
450      */
noopPathCounters()451     public static PathCounters noopPathCounters() {
452         return NoopPathCounters.INSTANCE;
453     }
454 }
455