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 */
017package org.apache.commons.io.comparator;
018
019import java.io.File;
020import java.io.Serializable;
021import java.util.Comparator;
022
023import org.apache.commons.io.FilenameUtils;
024import org.apache.commons.io.IOCase;
025
026/**
027 * Compare the file name <strong>extensions</strong> for order
028 * (see {@link FilenameUtils#getExtension(String)}).
029 * <p>
030 * This comparator can be used to sort lists or arrays of files
031 * by their file extension either in a case-sensitive, case-insensitive or
032 * system dependent case-sensitive way. A number of singleton instances
033 * are provided for the various case sensitivity options (using {@link IOCase})
034 * and the reverse of those options.
035 * </p>
036 * <p>
037 * Example of a <em>case-sensitive</em> file extension sort using the
038 * {@link #EXTENSION_COMPARATOR} singleton instance:
039 * </p>
040 * <pre>
041 *       List&lt;File&gt; list = ...
042 *       ((AbstractFileComparator) ExtensionFileComparator.EXTENSION_COMPARATOR).sort(list);
043 * </pre>
044 * <p>
045 * Example of a <em>reverse case-insensitive</em> file extension sort using the
046 * {@link #EXTENSION_INSENSITIVE_REVERSE} singleton instance:
047 * </p>
048 * <pre>
049 *       File[] array = ...
050 *       ((AbstractFileComparator) ExtensionFileComparator.EXTENSION_INSENSITIVE_REVERSE).sort(array);
051 * </pre>
052 * <h2>Deprecating Serialization</h2>
053 * <p>
054 * <em>Serialization is deprecated and will be removed in 3.0.</em>
055 * </p>
056 *
057 * @since 1.4
058 */
059public class ExtensionFileComparator extends AbstractFileComparator implements Serializable {
060
061    private static final long serialVersionUID = 1928235200184222815L;
062
063    /** Case-sensitive extension comparator instance (see {@link IOCase#SENSITIVE}) */
064    public static final Comparator<File> EXTENSION_COMPARATOR = new ExtensionFileComparator();
065
066    /** Reverse case-sensitive extension comparator instance (see {@link IOCase#SENSITIVE}) */
067    public static final Comparator<File> EXTENSION_REVERSE = new ReverseFileComparator(EXTENSION_COMPARATOR);
068
069    /** Case-insensitive extension comparator instance (see {@link IOCase#INSENSITIVE}) */
070    public static final Comparator<File> EXTENSION_INSENSITIVE_COMPARATOR
071                                                = new ExtensionFileComparator(IOCase.INSENSITIVE);
072
073    /** Reverse case-insensitive extension comparator instance (see {@link IOCase#INSENSITIVE}) */
074    public static final Comparator<File> EXTENSION_INSENSITIVE_REVERSE
075                                                = new ReverseFileComparator(EXTENSION_INSENSITIVE_COMPARATOR);
076
077    /** System sensitive extension comparator instance (see {@link IOCase#SYSTEM}) */
078    public static final Comparator<File> EXTENSION_SYSTEM_COMPARATOR = new ExtensionFileComparator(IOCase.SYSTEM);
079
080    /** Reverse system sensitive path comparator instance (see {@link IOCase#SYSTEM}) */
081    public static final Comparator<File> EXTENSION_SYSTEM_REVERSE = new ReverseFileComparator(EXTENSION_SYSTEM_COMPARATOR);
082
083    /** Whether the comparison is case-sensitive. */
084    private final IOCase ioCase;
085
086    /**
087     * Constructs a case-sensitive file extension comparator instance.
088     */
089    public ExtensionFileComparator() {
090        this.ioCase = IOCase.SENSITIVE;
091    }
092
093    /**
094     * Constructs a file extension comparator instance with the specified case-sensitivity.
095     *
096     * @param ioCase how to handle case sensitivity, null means case-sensitive
097     */
098    public ExtensionFileComparator(final IOCase ioCase) {
099        this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
100    }
101
102    /**
103     * Compares the extensions of two files the specified case sensitivity.
104     *
105     * @param file1 The first file to compare
106     * @param file2 The second file to compare
107     * @return a negative value if the first file's extension
108     * is less than the second, zero if the extensions are the
109     * same and a positive value if the first files extension
110     * is greater than the second file.
111     */
112    @Override
113    public int compare(final File file1, final File file2) {
114        final String suffix1 = FilenameUtils.getExtension(file1.getName());
115        final String suffix2 = FilenameUtils.getExtension(file2.getName());
116        return ioCase.checkCompareTo(suffix1, suffix2);
117    }
118
119    /**
120     * String representation of this file comparator.
121     *
122     * @return String representation of this file comparator
123     */
124    @Override
125    public String toString() {
126        return super.toString() + "[ioCase=" + ioCase + "]";
127    }
128}