    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    package org.apache.commons.io.comparator;
    018
    019    import java.io.File;
    020    import java.io.Serializable;
    021    import java.util.Comparator;
    022
    023    import org.apache.commons.io.FileUtils;
    024
    025    /**
    026     * Compare the <b>length/size</b> of two files for order (see
    027     * {@link File#length()} and {@link FileUtils#sizeOfDirectory(File)}).
    028     * <p>
    029     * This comparator can be used to sort lists or arrays of files
    030     * by their length/size.
    031     * <p>
    032     * Example of sorting a list of files using the
    033     * {@link #SIZE_COMPARATOR} singleton instance:
    034     * <pre>
    035     *       List&lt;File&gt; list = ...
    036     *       SizeFileComparator.SIZE_COMPARATOR.sort(list);
    037     * </pre>
    038     * <p>
    039     * Example of doing a <i>reverse</i> sort of an array of files using the
    040     * {@link #SIZE_REVERSE} singleton instance:
    041     * <pre>
    042     *       File[] array = ...
    043     *       SizeFileComparator.SIZE_REVERSE.sort(array);
    044     * </pre>
    045     * <p>
    046     * <strong>N.B.</strong> Directories are treated as <b>zero size</b> unless
    047     * <code>sumDirectoryContents</code> is <code>true</code>.
    048     *
    049     * @version $Revision: 723942 $ $Date: 2008-12-06 01:24:06 +0000 (Sat, 06 Dec 2008) $
    050     * @since Commons IO 1.4
    051     */
    052    public class SizeFileComparator extends AbstractFileComparator implements Serializable {
    053
    054        /** Size comparator instance - directories are treated as zero size */
    055        public static final Comparator<File> SIZE_COMPARATOR = new SizeFileComparator();
    056
    057        /** Reverse size comparator instance - directories are treated as zero size */
    058        public static final Comparator<File> SIZE_REVERSE = new ReverseComparator(SIZE_COMPARATOR);
    059
    060        /**
    061         * Size comparator instance which sums the size of a directory's contents
    062         * using {@link FileUtils#sizeOfDirectory(File)}
    063         */
    064        public static final Comparator<File> SIZE_SUMDIR_COMPARATOR = new SizeFileComparator(true);
    065
    066        /**
    067         * Reverse size comparator instance which sums the size of a directory's contents
    068         * using {@link FileUtils#sizeOfDirectory(File)}
    069         */
    070        public static final Comparator<File> SIZE_SUMDIR_REVERSE = new ReverseComparator(SIZE_SUMDIR_COMPARATOR);
    071
    072        /** Whether the sum of the directory's contents should be calculated. */
    073        private final boolean sumDirectoryContents;
    074
    075        /**
    076         * Construct a file size comparator instance (directories treated as zero size).
    077         */
    078        public SizeFileComparator() {
    079            this.sumDirectoryContents = false;
    080        }
    081
    082        /**
    083         * Construct a file size comparator instance specifying whether the size of
    084         * the directory contents should be aggregated.
    085         * <p>
    086         * If the <code>sumDirectoryContents</code> is <code>true</code> The size of
    087         * directories is calculated using  {@link FileUtils#sizeOfDirectory(File)}.
    088         *
    089         * @param sumDirectoryContents <code>true</code> if the sum of the directoryies contents
    090         *  should be calculated, otherwise <code>false</code> if directories should be treated
    091         *  as size zero (see {@link FileUtils#sizeOfDirectory(File)}).
    092         */
    093        public SizeFileComparator(boolean sumDirectoryContents) {
    094            this.sumDirectoryContents = sumDirectoryContents;
    095        }
    096
    097        /**
    098         * Compare the length of two files.
    099         *
    100         * @param file1 The first file to compare
    101         * @param file2 The second file to compare
    102         * @return a negative value if the first file's length
    103         * is less than the second, zero if the lengths are the
    104         * same and a positive value if the first files length
    105         * is greater than the second file.
    106         *
    107         */
    108        public int compare(File file1, File file2) {
    109            long size1 = 0;
    110            if (file1.isDirectory()) {
    111                size1 = sumDirectoryContents && file1.exists() ? FileUtils.sizeOfDirectory(file1) : 0;
    112            } else {
    113                size1 = file1.length();
    114            }
    115            long size2 = 0;
    116            if (file2.isDirectory()) {
    117                size2 = sumDirectoryContents && file2.exists() ? FileUtils.sizeOfDirectory(file2) : 0;
    118            } else {
    119                size2 = file2.length();
    120            }
    121            long result = size1 - size2;
    122            if (result < 0) {
    123                return -1;
    124            } else if (result > 0) {
    125                return 1;
    126            } else {
    127                return 0;
    128            }
    129        }
    130
    131        /**
    132         * String representation of this file comparator.
    133         *
    134         * @return String representation of this file comparator
    135         */
    136        @Override
    137        public String toString() {
    138            return super.toString() + "[sumDirectoryContents=" + sumDirectoryContents + "]";
    139        }
    140    }