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<File> list = ...
039 * comparator.sort(list);
040 * </pre>
041 *
042 * @version $Id: CompositeFileComparator.java 1304052 2012-03-22 20:55:29Z ggregory $
043 * @since 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 }