/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.io.comparator;

import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * Compare two files using a set of delegate file {@link Comparator}.
 * <p>
 * This comparator can be used to sort lists or arrays of files
 * by combining a number other comparators.
 * <p>
 * Example of sorting a list of files by type (i.e. directory or file)
 * and then by name:
 * <pre>
 *       CompositeFileComparator comparator =
 *                       new CompositeFileComparator(
 *                                   DirectoryFileComparator.DIRECTORY_COMPARATOR,
 *                                   NameFileComparator.NAME_COMPARATOR);
 *       List&lt;File&gt; list = ...
 *       comparator.sort(list);
 * </pre>
 *
 * @version $Revision$ $Date$
 * @since Commons IO 2.0
 */
public class CompositeFileComparator extends AbstractFileComparator implements Serializable {

    private static final Comparator[] NO_COMPARATORS = {};
    private final Comparator<File>[] delegates;

    /**
     * Create a composite comparator for the set of delegate comparators.
     *
     * @param delegates The delegate file comparators
     */
    public CompositeFileComparator(Comparator<File>... delegates) {
        if (delegates == null) {
            this.delegates = NO_COMPARATORS;
        } else {
            this.delegates = new Comparator[delegates.length];
            System.arraycopy(delegates, 0, this.delegates, 0, delegates.length);
        }
    }

    /**
     * Create a composite comparator for the set of delegate comparators.
     *
     * @param delegates The delegate file comparators
     */
    public CompositeFileComparator(Iterable<Comparator<File>> delegates) {
        if (delegates == null) {
            this.delegates = NO_COMPARATORS;
        } else {
            List<Comparator<File>> list = new ArrayList<Comparator<File>>();
            for (Comparator<File> comparator : delegates) {
                list.add(comparator);
            }
            this.delegates = list.toArray(new Comparator[list.size()]);
        }
    }

    /**
     * Compare the two files using delegate comparators.
     * 
     * @param file1 The first file to compare
     * @param file2 The second file to compare
     * @return the first non-zero result returned from
     * the delegate comparators or zero.
     */
    public int compare(File file1, File file2) {
        int result = 0;
        for (Comparator<File> delegate : delegates) {
            result = delegate.compare(file1, file2);
            if (result != 0) {
                break;
            }
        }
        return result;
    }

    /**
     * String representation of this file comparator.
     *
     * @return String representation of this file comparator
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(super.toString());
        builder.append('{');
        for (int i = 0; i < delegates.length; i++) {
            if (i > 0) {
                builder.append(',');
            }
            builder.append(delegates[i]);
        }
        builder.append('}');
        return builder.toString();
    }
}

@@ -1797,16 +1797,19 @@
 mparator
+%3C?%3E
 %5B%5D NO_CO
@@ -2016,32 +2016,127 @@
 arators%0A     */%0A
+    @SuppressWarnings(%22unchecked%22) // casts 1 & 2 must be OK because types are already correct%0A
     public Compo
@@ -2240,32 +2240,53 @@
 this.delegates =
+ (Comparator%3CFile%3E%5B%5D)
  NO_COMPARATORS;
@@ -2277,32 +2277,35 @@
  NO_COMPARATORS;
+//1
 %0A        %7D else 
@@ -2334,16 +2334,37 @@
 egates =
+ (Comparator%3CFile%3E%5B%5D)
  new Com
@@ -2370,16 +2370,19 @@
 mparator
+%3C?%3E
 %5Bdelegat
@@ -2392,16 +2392,19 @@
 length%5D;
+//2
 %0A       
@@ -2637,32 +2637,127 @@
 arators%0A     */%0A
+    @SuppressWarnings(%22unchecked%22) // casts 1 & 2 must be OK because types are already correct%0A
     public Compo
@@ -2876,16 +2876,37 @@
 egates =
+ (Comparator%3CFile%3E%5B%5D)
  NO_COMP
@@ -2913,16 +2913,20 @@
 ARATORS;
+ //1
 %0A       
@@ -3152,16 +3152,37 @@
 egates =
+ (Comparator%3CFile%3E%5B%5D)
  list.to
@@ -3201,16 +3201,19 @@
 mparator
+%3C?%3E
 %5Blist.si
@@ -3219,16 +3219,20 @@
 ize()%5D);
+ //2
 %0A       

Fix raw types for private variables