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