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.io.IOException;
21  import java.nio.file.FileVisitResult;
22  import java.nio.file.Files;
23  import java.nio.file.Path;
24  import java.nio.file.attribute.BasicFileAttributes;
25  import java.util.Objects;
26  
27  import org.apache.commons.io.file.Counters.PathCounters;
28  import org.apache.commons.io.filefilter.TrueFileFilter;
29  
30  /**
31   * Counts files, directories, and sizes, as a visit proceeds.
32   *
33   * @since 2.7
34   */
35  public class CountingPathVisitor extends SimplePathVisitor {
36  
37      static final String[] EMPTY_STRING_ARRAY = {};
38  
39      /**
40       * Creates a new instance configured with a BigInteger {@link PathCounters}.
41       *
42       * @return a new instance configured with a BigInteger {@link PathCounters}.
43       */
44      public static CountingPathVisitor withBigIntegerCounters() {
45          return new CountingPathVisitor(Counters.bigIntegerPathCounters());
46      }
47  
48      /**
49       * Creates a new instance configured with a long {@link PathCounters}.
50       *
51       * @return a new instance configured with a long {@link PathCounters}.
52       */
53      public static CountingPathVisitor withLongCounters() {
54          return new CountingPathVisitor(Counters.longPathCounters());
55      }
56  
57      private final PathCounters pathCounters;
58      private final PathFilter fileFilter;
59      private final PathFilter dirFilter;
60  
61      /**
62       * Constructs a new instance.
63       *
64       * @param pathCounter How to count path visits.
65       */
66      public CountingPathVisitor(final PathCounters pathCounter) {
67          this(pathCounter, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
68      }
69  
70      /**
71       * Constructs a new instance.
72       *
73       * @param pathCounter How to count path visits.
74       * @param fileFilter Filters which files to count.
75       * @param dirFilter Filters which directories to count.
76       * @since 2.9.0
77       */
78      public CountingPathVisitor(final PathCounters pathCounter, final PathFilterter.html#PathFilter">PathFilter fileFilter, final PathFilter dirFilter) {
79          this.pathCounters = Objects.requireNonNull(pathCounter, "pathCounter");
80          this.fileFilter = Objects.requireNonNull(fileFilter, "fileFilter");
81          this.dirFilter = Objects.requireNonNull(dirFilter, "dirFilter");
82      }
83  
84      @Override
85      public boolean equals(final Object obj) {
86          if (this == obj) {
87              return true;
88          }
89          if (!(obj instanceof CountingPathVisitor)) {
90              return false;
91          }
92          final CountingPathVisitor../org/apache/commons/io/file/CountingPathVisitor.html#CountingPathVisitor">CountingPathVisitor other = (CountingPathVisitor) obj;
93          return Objects.equals(pathCounters, other.pathCounters);
94      }
95  
96      /**
97       * Gets the visitation counts.
98       *
99       * @return the visitation counts.
100      */
101     public PathCounters getPathCounters() {
102         return pathCounters;
103     }
104 
105     @Override
106     public int hashCode() {
107         return Objects.hash(pathCounters);
108     }
109 
110     @Override
111     public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
112         updateDirCounter(dir, exc);
113         return FileVisitResult.CONTINUE;
114     }
115 
116     @Override
117     public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attributes) throws IOException {
118         final FileVisitResult accept = dirFilter.accept(dir, attributes);
119         return accept != FileVisitResult.CONTINUE ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
120     }
121 
122     @Override
123     public String toString() {
124         return pathCounters.toString();
125     }
126 
127     /**
128      * Updates the counter for visiting the given directory.
129      *
130      * @param dir the visited directory.
131      * @param exc Encountered exception.
132      * @since 2.9.0
133      */
134     protected void updateDirCounter(final Path dir, final IOException exc) {
135         pathCounters.getDirectoryCounter().increment();
136     }
137 
138     /**
139      * Updates the counters for visiting the given file.
140      *
141      * @param file the visited file.
142      * @param attributes the visited file attributes.
143      */
144     protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) {
145         pathCounters.getFileCounter().increment();
146         pathCounters.getByteCounter().add(attributes.size());
147     }
148 
149     @Override
150     public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException {
151         if (Files.exists(file) && fileFilter.accept(file, attributes) == FileVisitResult.CONTINUE) {
152             updateFileCounters(file, attributes);
153         }
154         return FileVisitResult.CONTINUE;
155     }
156 
157 }