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}