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    *      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           */
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
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
67          public Counter getByteCounter() {
68              return byteCounter;
69          }
70  
71          @Override
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
82          public Counter getFileCounter() {
83              return this.fileCounter;
84          }
85  
86          @Override
87          public int hashCode() {
88              return Objects.hash(byteCounter, directoryCounter, fileCounter);
89          }
90  
91          @Override
92          public void reset() {
93              byteCounter.reset();
94              directoryCounter.reset();
95              fileCounter.reset();
96          }
97  
98          @Override
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
114         public void add(final long val) {
115             value = value.add(BigInteger.valueOf(val));
116 
117         }
118 
119         @Override
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
132         public long get() {
133             return value.longValueExact();
134         }
135 
136         @Override
137         public BigInteger getBigInteger() {
138             return value;
139         }
140 
141         @Override
142         public Long getLong() {
143             return Long.valueOf(value.longValueExact());
144         }
145 
146         @Override
147         public int hashCode() {
148             return Objects.hash(value);
149         }
150 
151         @Override
152         public void increment() {
153             value = value.add(BigInteger.ONE);
154         }
155 
156         @Override
157         public void reset() {
158             value = BigInteger.ZERO;
159         }
160 
161         @Override
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          */
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          */
191         void add(long val);
192 
193         /**
194          * Gets the counter as a long.
195          *
196          * @return the counter as a long.
197          */
198         long get();
199 
200         /**
201          * Gets the counter as a BigInteger.
202          *
203          * @return the counter as a BigInteger.
204          */
205         BigInteger getBigInteger();
206 
207         /**
208          * Gets the counter as a Long.
209          *
210          * @return the counter as a Long.
211          */
212         Long getLong();
213 
214         /**
215          * Adds one to this counter.
216          */
217         void increment();
218 
219         /**
220          * Resets this count to 0.
221          */
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
236         public void add(final long add) {
237             value += add;
238 
239         }
240 
241         @Override
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
254         public long get() {
255             return value;
256         }
257 
258         @Override
259         public BigInteger getBigInteger() {
260             return BigInteger.valueOf(value);
261         }
262 
263         @Override
264         public Long getLong() {
265             return Long.valueOf(value);
266         }
267 
268         @Override
269         public int hashCode() {
270             return Objects.hash(value);
271         }
272 
273         @Override
274         public void increment() {
275             value++;
276         }
277 
278         @Override
279         public void reset() {
280             value = 0L;
281         }
282 
283         @Override
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          */
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
311         public void add(final long add) {
312             // noop
313         }
314 
315         @Override
316         public long get() {
317             return 0;
318         }
319 
320         @Override
321         public BigInteger getBigInteger() {
322             return BigInteger.ZERO;
323         }
324 
325         @Override
326         public Long getLong() {
327             return 0L;
328         }
329 
330         @Override
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
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          */
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          */
374         Counter getByteCounter();
375 
376         /**
377          * Gets the directory counter.
378          *
379          * @return the directory counter.
380          */
381         Counter getDirectoryCounter();
382 
383         /**
384          * Gets the file counter.
385          *
386          * @return the file counter.
387          */
388         Counter getFileCounter();
389 
390         /**
391          * Resets the counts to 0.
392          */
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      */
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      */
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      */
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      */
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      */
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      */
451     public static PathCounters noopPathCounters() {
452         return NoopPathCounters.INSTANCE;
453     }
454 }