    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.io.file;
    019
    020import java.math.BigInteger;
    021import java.util.Objects;
    022
    023/**
    024 * Provides counters for files, directories, and sizes, as a visit proceeds.
    025 *
    026 * @since 2.7
    027 */
    028public class Counters {
    029
    030    /**
    031     * Counts files, directories, and sizes, as a visit proceeds.
    032     */
    033    private static class AbstractPathCounters implements PathCounters {
    034
    035        private final Counter byteCounter;
    036        private final Counter directoryCounter;
    037        private final Counter fileCounter;
    038
    039        /**
    040         * Constructs a new instance.
    041         *
    042         * @param byteCounter the byte counter.
    043         * @param directoryCounter the directory counter.
    044         * @param fileCounter the file counter.
    045         */
    046        protected AbstractPathCounters(final Counter byteCounter, final Counter directoryCounter,
    047                final Counter fileCounter) {
    048            super();
    049            this.byteCounter = byteCounter;
    050            this.directoryCounter = directoryCounter;
    051            this.fileCounter = fileCounter;
    052        }
    053
    054        @Override
    055        public boolean equals(Object obj) {
    056            if (this == obj) {
    057                return true;
    058            }
    059            if (!(obj instanceof AbstractPathCounters)) {
    060                return false;
    061            }
    062            AbstractPathCounters other = (AbstractPathCounters) obj;
    063            return Objects.equals(byteCounter, other.byteCounter)
    064                    && Objects.equals(directoryCounter, other.directoryCounter)
    065                    && Objects.equals(fileCounter, other.fileCounter);
    066        }
    067
    068        @Override
    069        public Counter getByteCounter() {
    070            return byteCounter;
    071        }
    072
    073        @Override
    074        public Counter getDirectoryCounter() {
    075            return directoryCounter;
    076        }
    077
    078        /**
    079         * Gets the count of visited files.
    080         *
    081         * @return the byte count of visited files.
    082         */
    083        @Override
    084        public Counter getFileCounter() {
    085            return this.fileCounter;
    086        }
    087
    088        @Override
    089        public int hashCode() {
    090            return Objects.hash(byteCounter, directoryCounter, fileCounter);
    091        }
    092
    093        @Override
    094        public String toString() {
    095            return String.format("%,d files, %,d directories, %,d bytes", Long.valueOf(fileCounter.get()),
    096                    Long.valueOf(directoryCounter.get()), Long.valueOf(byteCounter.get()));
    097        }
    098
    099    }
    100
    101    /**
    102     * Counts using a BigInteger number.
    103     */
    104    private static class BigIntegerCounter implements Counter {
    105
    106        private BigInteger value = BigInteger.ZERO;
    107
    108        @Override
    109        public void add(final long val) {
    110            value = value.add(BigInteger.valueOf(val));
    111
    112        }
    113
    114        @Override
    115        public boolean equals(Object obj) {
    116            if (this == obj) {
    117                return true;
    118            }
    119            if (!(obj instanceof Counter)) {
    120                return false;
    121            }
    122            Counter other = (Counter) obj;
    123            return Objects.equals(value, other.getBigInteger());
    124        }
    125
    126        @Override
    127        public long get() {
    128            return value.longValueExact();
    129        }
    130
    131        @Override
    132        public BigInteger getBigInteger() {
    133            return value;
    134        }
    135
    136        @Override
    137        public Long getLong() {
    138            return Long.valueOf(value.longValueExact());
    139        }
    140
    141        @Override
    142        public int hashCode() {
    143            return Objects.hash(value);
    144        }
    145
    146        @Override
    147        public void increment() {
    148            value = value.add(BigInteger.ONE);
    149        }
    150
    151        @Override
    152        public String toString() {
    153            return value.toString();
    154        }
    155    }
    156
    157    /**
    158     * Counts files, directories, and sizes, as a visit proceeds, using BigInteger numbers.
    159     */
    160    private static class BigIntegerPathCounters extends AbstractPathCounters {
    161
    162        /**
    163         * Constructs a new initialized instance.
    164         */
    165        protected BigIntegerPathCounters() {
    166            super(Counters.bigIntegerCounter(), Counters.bigIntegerCounter(), Counters.bigIntegerCounter());
    167        }
    168
    169    }
    170
    171    /**
    172     * Counts using a number.
    173     */
    174    public interface Counter {
    175
    176        /**
    177         * Adds the given number to this counter.
    178         *
    179         * @param val the value to add.
    180         */
    181        void add(long val);
    182
    183        /**
    184         * Gets the counter as a long.
    185         *
    186         * @return the counter as a long.
    187         */
    188        long get();
    189
    190        /**
    191         * Gets the counter as a BigInteger.
    192         *
    193         * @return the counter as a BigInteger.
    194         */
    195        BigInteger getBigInteger();
    196
    197        /**
    198         * Gets the counter as a Long.
    199         *
    200         * @return the counter as a Long.
    201         */
    202        Long getLong();
    203
    204        /**
    205         * Adds one to this counter.
    206         */
    207        void increment();
    208
    209    }
    210
    211    /**
    212     * Counts using a long number.
    213     */
    214    private static class LongCounter implements Counter {
    215
    216        private long value;
    217
    218        @Override
    219        public void add(final long add) {
    220            value += add;
    221
    222        }
    223
    224        @Override
    225        public boolean equals(Object obj) {
    226            if (this == obj) {
    227                return true;
    228            }
    229            if (!(obj instanceof Counter)) {
    230                return false;
    231            }
    232            Counter other = (Counter) obj;
    233            return value == other.get();
    234        }
    235
    236        @Override
    237        public long get() {
    238            return value;
    239        }
    240
    241        @Override
    242        public BigInteger getBigInteger() {
    243            return BigInteger.valueOf(value);
    244        }
    245
    246        @Override
    247        public Long getLong() {
    248            return Long.valueOf(value);
    249        }
    250
    251        @Override
    252        public int hashCode() {
    253            return Objects.hash(value);
    254        }
    255
    256        @Override
    257        public void increment() {
    258            value++;
    259        }
    260
    261        @Override
    262        public String toString() {
    263            return Long.toString(value);
    264        }
    265    }
    266
    267    /**
    268     * Counts files, directories, and sizes, as a visit proceeds, using long numbers.
    269     */
    270    private static class LongPathCounters extends AbstractPathCounters {
    271
    272        /**
    273         * Constructs a new initialized instance.
    274         */
    275        protected LongPathCounters() {
    276            super(Counters.longCounter(), Counters.longCounter(), Counters.longCounter());
    277        }
    278
    279    }
    280
    281    /**
    282     * Counts files, directories, and sizes, as a visit proceeds.
    283     */
    284    public interface PathCounters {
    285
    286        /**
    287         * Gets the byte counter.
    288         *
    289         * @return the byte counter.
    290         */
    291        Counter getByteCounter();
    292
    293        /**
    294         * Gets the directory counter.
    295         *
    296         * @return the directory counter.
    297         */
    298        Counter getDirectoryCounter();
    299
    300        /**
    301         * Gets the file counter.
    302         *
    303         * @return the file counter.
    304         */
    305        Counter getFileCounter();
    306
    307    }
    308
    309    /**
    310     * Returns a new BigInteger Counter.
    311     *
    312     * @return a new BigInteger Counter.
    313     */
    314    public static Counter bigIntegerCounter() {
    315        return new BigIntegerCounter();
    316    }
    317
    318    /**
    319     * Returns a new BigInteger PathCounters.
    320     *
    321     * @return a new BigInteger PathCounters.
    322     */
    323    public static PathCounters bigIntegerPathCounters() {
    324        return new BigIntegerPathCounters();
    325    }
    326
    327    /**
    328     * Returns a new long Counter.
    329     *
    330     * @return a new long Counter.
    331     */
    332    public static Counter longCounter() {
    333        return new LongCounter();
    334    }
    335
    336    /**
    337     * Returns a new BigInteger PathCounters.
    338     *
    339     * @return a new BigInteger PathCounters.
    340     */
    341    public static PathCounters longPathCounters() {
    342        return new LongPathCounters();
    343    }
    344}