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.io.IOException; 021import java.nio.file.Path; 022import java.nio.file.attribute.BasicFileAttributes; 023import java.util.ArrayList; 024import java.util.Comparator; 025import java.util.List; 026import java.util.Objects; 027 028import org.apache.commons.io.file.Counters.PathCounters; 029 030/** 031 * Accumulates normalized paths during visitation. 032 * <p> 033 * Use with care on large file trees as each visited Path element is remembered. 034 * </p> 035 * <h2>Example</h2> 036 * 037 * <pre> 038 * Path dir = Paths.get(""); 039 * // We are interested in files older than one day 040 * long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000); 041 * AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoff)); 042 * // 043 * // Walk one dir 044 * Files.walkFileTree(dir, Collections.emptySet(), 1, visitor); 045 * System.out.println(visitor.getPathCounters()); 046 * System.out.println(visitor.getFileList()); 047 * // 048 * visitor.getPathCounters().reset(); 049 * // 050 * // Walk dir tree 051 * Files.walkFileTree(dir, visitor); 052 * System.out.println(visitor.getPathCounters()); 053 * System.out.println(visitor.getDirList()); 054 * System.out.println(visitor.getFileList()); 055 * </pre> 056 * 057 * @since 2.7 058 */ 059public class AccumulatorPathVisitor extends CountingPathVisitor { 060 061 /** 062 * Creates a new instance configured with a BigInteger {@link PathCounters}. 063 * 064 * @return a new instance configured with a BigInteger {@link PathCounters}. 065 */ 066 public static AccumulatorPathVisitor withBigIntegerCounters() { 067 return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters()); 068 } 069 070 /** 071 * Creates a new instance configured with a BigInteger {@link PathCounters}. 072 * 073 * @param fileFilter Filters files to accumulate and count. 074 * @param dirFilter Filters directories to accumulate and count. 075 * @return a new instance configured with a long {@link PathCounters}. 076 * @since 2.9.0 077 */ 078 public static AccumulatorPathVisitor withBigIntegerCounters(final PathFilter fileFilter, 079 final PathFilter dirFilter) { 080 return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters(), fileFilter, dirFilter); 081 } 082 083 /** 084 * Creates a new instance configured with a long {@link PathCounters}. 085 * 086 * @return a new instance configured with a long {@link PathCounters}. 087 */ 088 public static AccumulatorPathVisitor withLongCounters() { 089 return new AccumulatorPathVisitor(Counters.longPathCounters()); 090 } 091 092 /** 093 * Creates a new instance configured with a long {@link PathCounters}. 094 * 095 * @param fileFilter Filters files to accumulate and count. 096 * @param dirFilter Filters directories to accumulate and count. 097 * @return a new instance configured with a long {@link PathCounters}. 098 * @since 2.9.0 099 */ 100 public static AccumulatorPathVisitor withLongCounters(final PathFilter fileFilter, final PathFilter dirFilter) { 101 return new AccumulatorPathVisitor(Counters.longPathCounters(), fileFilter, dirFilter); 102 } 103 104 private final List<Path> dirList = new ArrayList<>(); 105 106 private final List<Path> fileList = new ArrayList<>(); 107 108 /** 109 * Constructs a new instance. 110 * 111 * @since 2.9.0 112 */ 113 public AccumulatorPathVisitor() { 114 super(Counters.noopPathCounters()); 115 } 116 117 /** 118 * Constructs a new instance that counts file system elements. 119 * 120 * @param pathCounter How to count path visits. 121 */ 122 public AccumulatorPathVisitor(final PathCounters pathCounter) { 123 super(pathCounter); 124 } 125 126 /** 127 * Constructs a new instance. 128 * 129 * @param pathCounter How to count path visits. 130 * @param fileFilter Filters which files to count. 131 * @param dirFilter Filters which directories to count. 132 * @since 2.9.0 133 */ 134 public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, 135 final PathFilter dirFilter) { 136 super(pathCounter, fileFilter, dirFilter); 137 } 138 139 private void add(final List<Path> list, final Path dir) { 140 list.add(dir.normalize()); 141 } 142 143 @Override 144 public boolean equals(final Object obj) { 145 if (this == obj) { 146 return true; 147 } 148 if (!super.equals(obj)) { 149 return false; 150 } 151 if (!(obj instanceof AccumulatorPathVisitor)) { 152 return false; 153 } 154 final AccumulatorPathVisitor other = (AccumulatorPathVisitor) obj; 155 return Objects.equals(dirList, other.dirList) && Objects.equals(fileList, other.fileList); 156 } 157 158 /** 159 * Gets the list of visited directories. 160 * 161 * @return the list of visited directories. 162 */ 163 public List<Path> getDirList() { 164 return dirList; 165 } 166 167 /** 168 * Gets the list of visited files. 169 * 170 * @return the list of visited files. 171 */ 172 public List<Path> getFileList() { 173 return fileList; 174 } 175 176 @Override 177 public int hashCode() { 178 final int prime = 31; 179 int result = super.hashCode(); 180 result = prime * result + Objects.hash(dirList, fileList); 181 return result; 182 } 183 184 /** 185 * Relativizes each directory path with {@link Path#relativize(Path)} against the given {@code parent}, optionally 186 * sorting the result. 187 * 188 * @param parent A parent path 189 * @param sort Whether to sort 190 * @param comparator How to sort, null uses default sorting. 191 * @return A new list 192 */ 193 public List<Path> relativizeDirectories(final Path parent, final boolean sort, 194 final Comparator<? super Path> comparator) { 195 return PathUtils.relativize(getDirList(), parent, sort, comparator); 196 } 197 198 /** 199 * Relativizes each file path with {@link Path#relativize(Path)} against the given {@code parent}, optionally 200 * sorting the result. 201 * 202 * @param parent A parent path 203 * @param sort Whether to sort 204 * @param comparator How to sort, null uses default sorting. 205 * @return A new list 206 */ 207 public List<Path> relativizeFiles(final Path parent, final boolean sort, 208 final Comparator<? super Path> comparator) { 209 return PathUtils.relativize(getFileList(), parent, sort, comparator); 210 } 211 212 @Override 213 protected void updateDirCounter(final Path dir, final IOException exc) { 214 super.updateDirCounter(dir, exc); 215 add(dirList, dir); 216 } 217 218 @Override 219 protected void updateFileCounters(final Path file, final BasicFileAttributes attributes) { 220 super.updateFileCounters(file, attributes); 221 add(fileList, file); 222 } 223 224}