    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.ArrayList;
    022    import java.util.Comparator;
    023    import java.util.List;
    024
    025    /**
    026     * Compare two files using a set of delegate file {@link Comparator}.
    027     * <p>
    028     * This comparator can be used to sort lists or arrays of files
    029     * by combining a number other comparators.
    030     * <p>
    031     * Example of sorting a list of files by type (i.e. directory or file)
    032     * and then by name:
    033     * <pre>
    034     *       CompositeFileComparator comparator =
    035     *                       new CompositeFileComparator(
    036     *                                   DirectoryFileComparator.DIRECTORY_COMPARATOR,
    037     *                                   NameFileComparator.NAME_COMPARATOR);
    038     *       List&lt;File&gt; list = ...
    039     *       comparator.sort(list);
    040     * </pre>
    041     *
    042     * @version $Revision: 896991 $ $Date: 2010-01-07 20:03:42 +0000 (Thu, 07 Jan 2010) $
    043     * @since Commons IO 2.0
    044     */
    045    public class CompositeFileComparator extends AbstractFileComparator implements Serializable {
    046
    047        private static final Comparator<?>[] NO_COMPARATORS = {};
    048        private final Comparator<File>[] delegates;
    049
    050        /**
    051         * Create a composite comparator for the set of delegate comparators.
    052         *
    053         * @param delegates The delegate file comparators
    054         */
    055        @SuppressWarnings("unchecked") // casts 1 & 2 must be OK because types are already correct
    056        public CompositeFileComparator(Comparator<File>... delegates) {
    057            if (delegates == null) {
    058                this.delegates = (Comparator<File>[]) NO_COMPARATORS;//1
    059            } else {
    060                this.delegates = (Comparator<File>[]) new Comparator<?>[delegates.length];//2
    061                System.arraycopy(delegates, 0, this.delegates, 0, delegates.length);
    062            }
    063        }
    064
    065        /**
    066         * Create a composite comparator for the set of delegate comparators.
    067         *
    068         * @param delegates The delegate file comparators
    069         */
    070        @SuppressWarnings("unchecked") // casts 1 & 2 must be OK because types are already correct
    071        public CompositeFileComparator(Iterable<Comparator<File>> delegates) {
    072            if (delegates == null) {
    073                this.delegates = (Comparator<File>[]) NO_COMPARATORS; //1
    074            } else {
    075                List<Comparator<File>> list = new ArrayList<Comparator<File>>();
    076                for (Comparator<File> comparator : delegates) {
    077                    list.add(comparator);
    078                }
    079                this.delegates = (Comparator<File>[]) list.toArray(new Comparator<?>[list.size()]); //2
    080            }
    081        }
    082
    083        /**
    084         * Compare the two files using delegate comparators.
    085         *
    086         * @param file1 The first file to compare
    087         * @param file2 The second file to compare
    088         * @return the first non-zero result returned from
    089         * the delegate comparators or zero.
    090         */
    091        public int compare(File file1, File file2) {
    092            int result = 0;
    093            for (Comparator<File> delegate : delegates) {
    094                result = delegate.compare(file1, file2);
    095                if (result != 0) {
    096                    break;
    097                }
    098            }
    099            return result;
    100        }
    101
    102        /**
    103         * String representation of this file comparator.
    104         *
    105         * @return String representation of this file comparator
    106         */
    107        @Override
    108        public String toString() {
    109            StringBuilder builder = new StringBuilder();
    110            builder.append(super.toString());
    111            builder.append('{');
    112            for (int i = 0; i < delegates.length; i++) {
    113                if (i > 0) {
    114                    builder.append(',');
    115                }
    116                builder.append(delegates[i]);
    117            }
    118            builder.append('}');
    119            return builder.toString();
    120        }
    121    }