    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.FileVisitResult;
    022import java.nio.file.Files;
    023import java.nio.file.Path;
    024import java.nio.file.attribute.BasicFileAttributes;
    025import java.util.ArrayList;
    026import java.util.Comparator;
    027import java.util.List;
    028import java.util.Objects;
    029
    030import org.apache.commons.io.file.Counters.PathCounters;
    031
    032/**
    033 * Accumulates normalized paths during visitation.
    034 * <p>
    035 * Use with care on large file trees as each visited Path element is remembered.
    036 * </p>
    037 *
    038 * @since 2.7
    039 */
    040public class AccumulatorPathVisitor extends CountingPathVisitor {
    041
    042    /**
    043     * Creates a new instance configured with a BigInteger {@link PathCounters}.
    044     *
    045     * @return a new instance configured with a BigInteger {@link PathCounters}.
    046     */
    047    public static AccumulatorPathVisitor withBigIntegerCounters() {
    048        return new AccumulatorPathVisitor(Counters.bigIntegerPathCounters());
    049    }
    050
    051    /**
    052     * Creates a new instance configured with a long {@link PathCounters}.
    053     *
    054     * @return a new instance configured with a long {@link PathCounters}.
    055     */
    056    public static AccumulatorPathVisitor withLongCounters() {
    057        return new AccumulatorPathVisitor(Counters.longPathCounters());
    058    }
    059
    060    private final List<Path> dirList = new ArrayList<>();
    061
    062    private final List<Path> fileList = new ArrayList<>();
    063
    064    /**
    065     * Constructs a new instance.
    066     *
    067     * @param pathCounter How to count path visits.
    068     */
    069    public AccumulatorPathVisitor(final PathCounters pathCounter) {
    070        super(pathCounter);
    071    }
    072
    073    @Override
    074    public boolean equals(final Object obj) {
    075        if (this == obj) {
    076            return true;
    077        }
    078        if (!super.equals(obj)) {
    079            return false;
    080        }
    081        if (!(obj instanceof AccumulatorPathVisitor)) {
    082            return false;
    083        }
    084        final AccumulatorPathVisitor other = (AccumulatorPathVisitor) obj;
    085        return Objects.equals(dirList, other.dirList) && Objects.equals(fileList, other.fileList);
    086    }
    087
    088    /**
    089     * Gets the list of visited directories.
    090     *
    091     * @return the list of visited directories.
    092     */
    093    public List<Path> getDirList() {
    094        return dirList;
    095    }
    096
    097    /**
    098     * Gets the list of visited files.
    099     *
    100     * @return the list of visited files.
    101     */
    102    public List<Path> getFileList() {
    103        return fileList;
    104    }
    105
    106    @Override
    107    public int hashCode() {
    108        final int prime = 31;
    109        int result = super.hashCode();
    110        result = prime * result + Objects.hash(dirList, fileList);
    111        return result;
    112    }
    113
    114    /**
    115     * Relativizes each directory path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
    116     * sorting the result.
    117     *
    118     * @param parent A parent path
    119     * @param sort Whether to sort
    120     * @param comparator How to sort, null uses default sorting.
    121     * @return A new list
    122     */
    123    public List<Path> relativizeDirectories(final Path parent, final boolean sort, final Comparator<? super Path> comparator) {
    124        return PathUtils.relativize(getDirList(), parent, sort, comparator);
    125    }
    126
    127    /**
    128     * Relativizes each file path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
    129     * sorting the result.
    130     *
    131     * @param parent A parent path
    132     * @param sort Whether to sort
    133     * @param comparator How to sort, null uses default sorting.
    134     * @return A new list
    135     */
    136    public List<Path> relativizeFiles(final Path parent, final boolean sort, final Comparator<? super Path> comparator) {
    137        return PathUtils.relativize(getFileList(), parent, sort, comparator);
    138    }
    139
    140    @Override
    141    public FileVisitResult visitFile(final Path file, final BasicFileAttributes attributes) throws IOException {
    142        ((Files.isDirectory(file)) ? dirList : fileList).add(file.normalize());
    143        return super.visitFile(file, attributes);
    144    }
    145
    146}