• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Path;
23 import java.nio.file.attribute.BasicFileAttributes;
24 import java.util.ArrayList;
25 import java.util.Comparator;
26 import java.util.List;
27 import java.util.Objects;
28 
29 import org.apache.commons.io.file.Counters.PathCounters;
30 import org.apache.commons.io.function.IOBiFunction;
31 
32 /**
33  * Accumulates normalized paths during visitation.
34  * <p>
35  * Use with care on large file trees as each visited Path element is remembered.
36  * </p>
37  * <h2>Example</h2>
38  *
39  * <pre>
40  * Path dir = PathUtils.current();
41  * // We are interested in files older than one day
42  * Instant cutoff = Instant.now().minus(Duration.ofDays(1));
43  * AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoff));
44  * //
45  * // Walk one dir
46  * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor);
47  * System.out.println(visitor.getPathCounters());
48  * System.out.println(visitor.getFileList());
49  * //
50  * visitor.getPathCounters().reset();
51  * //
52  * // Walk dir tree
53  * Files.walkFileTree(dir, visitor);
54  * System.out.println(visitor.getPathCounters());
55  * System.out.println(visitor.getDirList());
56  * System.out.println(visitor.getFileList());
57  * </pre>
58  *
59  * @since 2.7
60  */
61 public class AccumulatorPathVisitor extends CountingPathVisitor {
62 
63     /**
64      * Creates a new instance configured with a BigInteger {@link PathCounters}.
65      *
66      * @return a new instance configured with a BigInteger {@link PathCounters}.
67      */
withBigIntegerCounters()68     public static AccumulatorPathVisitor withBigIntegerCounters() {
69         return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters());
70     }
71 
72     /**
73      * Creates a new instance configured with a BigInteger {@link PathCounters}.
74      *
75      * @param fileFilter Filters files to accumulate and count.
76      * @param dirFilter Filters directories to accumulate and count.
77      * @return a new instance configured with a long {@link PathCounters}.
78      * @since 2.9.0
79      */
withBigIntegerCounters(final PathFilter fileFilter, final PathFilter dirFilter)80     public static AccumulatorPathVisitor withBigIntegerCounters(final PathFilter fileFilter,
81         final PathFilter dirFilter) {
82         return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters(), fileFilter, dirFilter);
83     }
84 
85     /**
86      * Creates a new instance configured with a long {@link PathCounters}.
87      *
88      * @return a new instance configured with a long {@link PathCounters}.
89      */
withLongCounters()90     public static AccumulatorPathVisitor withLongCounters() {
91         return new AccumulatorPathVisitor(Counters.longPathCounters());
92     }
93 
94     /**
95      * Creates a new instance configured with a long {@link PathCounters}.
96      *
97      * @param fileFilter Filters files to accumulate and count.
98      * @param dirFilter Filters directories to accumulate and count.
99      * @return a new instance configured with a long {@link PathCounters}.
100      * @since 2.9.0
101      */
withLongCounters(final PathFilter fileFilter, final PathFilter dirFilter)102     public static AccumulatorPathVisitor withLongCounters(final PathFilter fileFilter, final PathFilter dirFilter) {
103         return new AccumulatorPathVisitor(Counters.longPathCounters(), fileFilter, dirFilter);
104     }
105 
106     private final List<Path> dirList = new ArrayList<>();
107 
108     private final List<Path> fileList = new ArrayList<>();
109 
110     /**
111      * Constructs a new instance.
112      *
113      * @since 2.9.0
114      */
AccumulatorPathVisitor()115     public AccumulatorPathVisitor() {
116         super(Counters.noopPathCounters());
117     }
118 
119     /**
120      * Constructs a new instance that counts file system elements.
121      *
122      * @param pathCounter How to count path visits.
123      */
AccumulatorPathVisitor(final PathCounters pathCounter)124     public AccumulatorPathVisitor(final PathCounters pathCounter) {
125         super(pathCounter);
126     }
127 
128     /**
129      * Constructs a new instance.
130      *
131      * @param pathCounter How to count path visits.
132      * @param fileFilter Filters which files to count.
133      * @param dirFilter Filters which directories to count.
134      * @since 2.9.0
135      */
AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter)136     public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter) {
137         super(pathCounter, fileFilter, dirFilter);
138     }
139 
140     /**
141      * Constructs a new instance.
142      *
143      * @param pathCounter How to count path visits.
144      * @param fileFilter Filters which files to count.
145      * @param dirFilter Filters which directories to count.
146      * @param visitFileFailed Called on {@link #visitFileFailed(Path, IOException)}.
147      * @since 2.12.0
148      */
AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter, final IOBiFunction<Path, IOException, FileVisitResult> visitFileFailed)149     public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter,
150         final IOBiFunction<Path, IOException, FileVisitResult> visitFileFailed) {
151         super(pathCounter, fileFilter, dirFilter, visitFileFailed);
152     }
153 
add(final List<Path> list, final Path dir)154     private void add(final List<Path> list, final Path dir) {
155         list.add(dir.normalize());
156     }
157 
158     @Override
equals(final Object obj)159     public boolean equals(final Object obj) {
160         if (this == obj) {
161             return true;
162         }
163         if (!super.equals(obj)) {
164             return false;
165         }
166         if (!(obj instanceof AccumulatorPathVisitor)) {
167             return false;
168         }
169         final AccumulatorPathVisitor other = (AccumulatorPathVisitor) obj;
170         return Objects.equals(dirList, other.dirList) && Objects.equals(fileList, other.fileList);
171     }
172 
173     /**
174      * Gets the list of visited directories.
175      *
176      * @return the list of visited directories.
177      */
getDirList()178     public List<Path> getDirList() {
179         return dirList;
180     }
181 
182     /**
183      * Gets the list of visited files.
184      *
185      * @return the list of visited files.
186      */
getFileList()187     public List<Path> getFileList() {
188         return fileList;
189     }
190 
191     @Override
hashCode()192     public int hashCode() {
193         final int prime = 31;
194         int result = super.hashCode();
195         result = prime * result + Objects.hash(dirList, fileList);
196         return result;
197     }
198 
199     /**
200      * Relativizes each directory path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
201      * sorting the result.
202      *
203      * @param parent A parent path
204      * @param sort Whether to sort
205      * @param comparator How to sort, null uses default sorting.
206      * @return A new list
207      */
relativizeDirectories(final Path parent, final boolean sort, final Comparator<? super Path> comparator)208     public List<Path> relativizeDirectories(final Path parent, final boolean sort,
209         final Comparator<? super Path> comparator) {
210         return PathUtils.relativize(getDirList(), parent, sort, comparator);
211     }
212 
213     /**
214      * Relativizes each file path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
215      * sorting the result.
216      *
217      * @param parent A parent path
218      * @param sort Whether to sort
219      * @param comparator How to sort, null uses default sorting.
220      * @return A new list
221      */
relativizeFiles(final Path parent, final boolean sort, final Comparator<? super Path> comparator)222     public List<Path> relativizeFiles(final Path parent, final boolean sort,
223         final Comparator<? super Path> comparator) {
224         return PathUtils.relativize(getFileList(), parent, sort, comparator);
225     }
226 
227     @Override
updateDirCounter(final Path dir, final IOException exc)228     protected void updateDirCounter(final Path dir, final IOException exc) {
229         super.updateDirCounter(dir, exc);
230         add(dirList, dir);
231     }
232 
233     @Override
updateFileCounters(final Path file, final BasicFileAttributes attributes)234     protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) {
235         super.updateFileCounters(file, attributes);
236         add(fileList, file);
237     }
238 
239 }
240