Counters.java

  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. package org.apache.commons.io.file;

  18. import java.math.BigInteger;
  19. import java.util.Objects;

  20. /**
  21.  * Provides counters for files, directories, and sizes, as a visit proceeds.
  22.  *
  23.  * @since 2.7
  24.  */
  25. public class Counters {

  26.     /**
  27.      * Counts files, directories, and sizes, as a visit proceeds.
  28.      */
  29.     private static class AbstractPathCounters implements PathCounters {

  30.         private final Counter byteCounter;
  31.         private final Counter directoryCounter;
  32.         private final Counter fileCounter;

  33.         /**
  34.          * Constructs a new instance.
  35.          *
  36.          * @param byteCounter the byte counter.
  37.          * @param directoryCounter the directory counter.
  38.          * @param fileCounter the file counter.
  39.          */
  40.         protected AbstractPathCounters(final Counter byteCounter, final Counter directoryCounter, final Counter fileCounter) {
  41.             this.byteCounter = byteCounter;
  42.             this.directoryCounter = directoryCounter;
  43.             this.fileCounter = fileCounter;
  44.         }

  45.         @Override
  46.         public boolean equals(final Object obj) {
  47.             if (this == obj) {
  48.                 return true;
  49.             }
  50.             if (!(obj instanceof AbstractPathCounters)) {
  51.                 return false;
  52.             }
  53.             final AbstractPathCounters other = (AbstractPathCounters) obj;
  54.             return Objects.equals(byteCounter, other.byteCounter)
  55.                 && Objects.equals(directoryCounter, other.directoryCounter)
  56.                 && Objects.equals(fileCounter, other.fileCounter);
  57.         }

  58.         @Override
  59.         public Counter getByteCounter() {
  60.             return byteCounter;
  61.         }

  62.         @Override
  63.         public Counter getDirectoryCounter() {
  64.             return directoryCounter;
  65.         }

  66.         /**
  67.          * Gets the count of visited files.
  68.          *
  69.          * @return the byte count of visited files.
  70.          */
  71.         @Override
  72.         public Counter getFileCounter() {
  73.             return this.fileCounter;
  74.         }

  75.         @Override
  76.         public int hashCode() {
  77.             return Objects.hash(byteCounter, directoryCounter, fileCounter);
  78.         }

  79.         @Override
  80.         public void reset() {
  81.             byteCounter.reset();
  82.             directoryCounter.reset();
  83.             fileCounter.reset();
  84.         }

  85.         @Override
  86.         public String toString() {
  87.             return String.format("%,d files, %,d directories, %,d bytes", Long.valueOf(fileCounter.get()),
  88.                 Long.valueOf(directoryCounter.get()), Long.valueOf(byteCounter.get()));
  89.         }

  90.     }

  91.     /**
  92.      * Counts using a {@link BigInteger} number.
  93.      */
  94.     private static final class BigIntegerCounter implements Counter {

  95.         private BigInteger value = BigInteger.ZERO;

  96.         @Override
  97.         public void add(final long val) {
  98.             value = value.add(BigInteger.valueOf(val));

  99.         }

  100.         @Override
  101.         public boolean equals(final Object obj) {
  102.             if (this == obj) {
  103.                 return true;
  104.             }
  105.             if (!(obj instanceof Counter)) {
  106.                 return false;
  107.             }
  108.             final Counter other = (Counter) obj;
  109.             return Objects.equals(value, other.getBigInteger());
  110.         }

  111.         @Override
  112.         public long get() {
  113.             return value.longValueExact();
  114.         }

  115.         @Override
  116.         public BigInteger getBigInteger() {
  117.             return value;
  118.         }

  119.         @Override
  120.         public Long getLong() {
  121.             return Long.valueOf(value.longValueExact());
  122.         }

  123.         @Override
  124.         public int hashCode() {
  125.             return Objects.hash(value);
  126.         }

  127.         @Override
  128.         public void increment() {
  129.             value = value.add(BigInteger.ONE);
  130.         }

  131.         @Override
  132.         public void reset() {
  133.             value = BigInteger.ZERO;
  134.         }

  135.         @Override
  136.         public String toString() {
  137.             return value.toString();
  138.         }
  139.     }

  140.     /**
  141.      * Counts files, directories, and sizes, as a visit proceeds, using BigInteger numbers.
  142.      */
  143.     private static final class BigIntegerPathCounters extends AbstractPathCounters {

  144.         /**
  145.          * Constructs a new initialized instance.
  146.          */
  147.         protected BigIntegerPathCounters() {
  148.             super(bigIntegerCounter(), bigIntegerCounter(), bigIntegerCounter());
  149.         }

  150.     }

  151.     /**
  152.      * Counts using a number.
  153.      */
  154.     public interface Counter {

  155.         /**
  156.          * Adds the given number to this counter.
  157.          *
  158.          * @param val the value to add.
  159.          */
  160.         void add(long val);

  161.         /**
  162.          * Gets the counter as a long.
  163.          *
  164.          * @return the counter as a long.
  165.          */
  166.         long get();

  167.         /**
  168.          * Gets the counter as a BigInteger.
  169.          *
  170.          * @return the counter as a BigInteger.
  171.          */
  172.         BigInteger getBigInteger();

  173.         /**
  174.          * Gets the counter as a Long.
  175.          *
  176.          * @return the counter as a Long.
  177.          */
  178.         Long getLong();

  179.         /**
  180.          * Adds one to this counter.
  181.          */
  182.         void increment();

  183.         /**
  184.          * Resets this count to 0.
  185.          */
  186.         default void reset() {
  187.             // binary compat, do nothing
  188.         }

  189.     }

  190.     /**
  191.      * Counts using a {@code long} number.
  192.      */
  193.     private static final class LongCounter implements Counter {

  194.         private long value;

  195.         @Override
  196.         public void add(final long add) {
  197.             value += add;

  198.         }

  199.         @Override
  200.         public boolean equals(final Object obj) {
  201.             if (this == obj) {
  202.                 return true;
  203.             }
  204.             if (!(obj instanceof Counter)) {
  205.                 return false;
  206.             }
  207.             final Counter other = (Counter) obj;
  208.             return value == other.get();
  209.         }

  210.         @Override
  211.         public long get() {
  212.             return value;
  213.         }

  214.         @Override
  215.         public BigInteger getBigInteger() {
  216.             return BigInteger.valueOf(value);
  217.         }

  218.         @Override
  219.         public Long getLong() {
  220.             return Long.valueOf(value);
  221.         }

  222.         @Override
  223.         public int hashCode() {
  224.             return Objects.hash(value);
  225.         }

  226.         @Override
  227.         public void increment() {
  228.             value++;
  229.         }

  230.         @Override
  231.         public void reset() {
  232.             value = 0L;
  233.         }

  234.         @Override
  235.         public String toString() {
  236.             return Long.toString(value);
  237.         }
  238.     }

  239.     /**
  240.      * Counts files, directories, and sizes, as a visit proceeds, using long numbers.
  241.      */
  242.     private static final class LongPathCounters extends AbstractPathCounters {

  243.         /**
  244.          * Constructs a new initialized instance.
  245.          */
  246.         protected LongPathCounters() {
  247.             super(longCounter(), longCounter(), longCounter());
  248.         }

  249.     }

  250.     /**
  251.      * Counts nothing.
  252.      */
  253.     private static final class NoopCounter implements Counter {

  254.         static final NoopCounter INSTANCE = new NoopCounter();

  255.         @Override
  256.         public void add(final long add) {
  257.             // noop
  258.         }

  259.         @Override
  260.         public long get() {
  261.             return 0;
  262.         }

  263.         @Override
  264.         public BigInteger getBigInteger() {
  265.             return BigInteger.ZERO;
  266.         }

  267.         @Override
  268.         public Long getLong() {
  269.             return 0L;
  270.         }

  271.         @Override
  272.         public void increment() {
  273.             // noop
  274.         }

  275.         /**
  276.          * Returns {@code "0"}, always.
  277.          *
  278.          * @return {@code "0"}, always.
  279.          * @since 2.12.0
  280.          */
  281.         @Override
  282.         public String toString() {
  283.             return "0";
  284.         }

  285.     }

  286.     /**
  287.      * Counts nothing.
  288.      */
  289.     private static final class NoopPathCounters extends AbstractPathCounters {

  290.         static final NoopPathCounters INSTANCE = new NoopPathCounters();

  291.         /**
  292.          * Constructs a new initialized instance.
  293.          */
  294.         private NoopPathCounters() {
  295.             super(noopCounter(), noopCounter(), noopCounter());
  296.         }

  297.     }

  298.     /**
  299.      * Counts files, directories, and sizes, as a visit proceeds.
  300.      */
  301.     public interface PathCounters {

  302.         /**
  303.          * Gets the byte counter.
  304.          *
  305.          * @return the byte counter.
  306.          */
  307.         Counter getByteCounter();

  308.         /**
  309.          * Gets the directory counter.
  310.          *
  311.          * @return the directory counter.
  312.          */
  313.         Counter getDirectoryCounter();

  314.         /**
  315.          * Gets the file counter.
  316.          *
  317.          * @return the file counter.
  318.          */
  319.         Counter getFileCounter();

  320.         /**
  321.          * Resets the counts to 0.
  322.          */
  323.         default void reset() {
  324.             // binary compat, do nothing
  325.         }

  326.     }

  327.     /**
  328.      * Returns a new BigInteger Counter.
  329.      *
  330.      * @return a new BigInteger Counter.
  331.      */
  332.     public static Counter bigIntegerCounter() {
  333.         return new BigIntegerCounter();
  334.     }

  335.     /**
  336.      * Returns a new BigInteger PathCounters.
  337.      *
  338.      * @return a new BigInteger PathCounters.
  339.      */
  340.     public static PathCounters bigIntegerPathCounters() {
  341.         return new BigIntegerPathCounters();
  342.     }

  343.     /**
  344.      * Returns a new long Counter.
  345.      *
  346.      * @return a new long Counter.
  347.      */
  348.     public static Counter longCounter() {
  349.         return new LongCounter();
  350.     }

  351.     /**
  352.      * Returns a new BigInteger PathCounters.
  353.      *
  354.      * @return a new BigInteger PathCounters.
  355.      */
  356.     public static PathCounters longPathCounters() {
  357.         return new LongPathCounters();
  358.     }

  359.     /**
  360.      * Returns the no-op Counter.
  361.      *
  362.      * @return the no-op Counter.
  363.      * @since 2.9.0
  364.      */
  365.     public static Counter noopCounter() {
  366.         return NoopCounter.INSTANCE;
  367.     }

  368.     /**
  369.      * Returns the no-op PathCounters.
  370.      *
  371.      * @return the no-op PathCounters.
  372.      * @since 2.9.0
  373.      */
  374.     public static PathCounters noopPathCounters() {
  375.         return NoopPathCounters.INSTANCE;
  376.     }

  377.     /**
  378.      * Construct a new instance.
  379.      *
  380.      * @deprecated Will be private in 4.0
  381.      */
  382.     @Deprecated
  383.     public Counters() {
  384.         // empty
  385.     }
  386. }