package com.dropbox.sync.android.util;
import java.text.Collator;
import java.util.Comparator;
import java.util.Locale;
import com.dropbox.sync.android.DbxFileInfo;
/**
* Comparator providing a reasonable sort order for displaying folder listings to
* a user. This comparator groups folders together, and properly deals with
* international characters in paths. This comparator will give a predictable
* sort order for file info from multiple folders, but may not provide the ideal
* user-displayed sort order for such a case.
*/
public class FolderListComparator implements Comparator<DbxFileInfo> {
private final boolean isNameFirst;
private final boolean isAscending;
/**
* Gets a comparator whose sort order places name before date.
*
* @param ascending whether the sort order should be ascending,
* vs. descending (reversed).
*/
public static FolderListComparator getNameFirst(boolean ascending) {
return new FolderListComparator(true, ascending);
}
/**
* Gets a comparator whose sort order places name before date.
*
* @param ascending whether the sort order should be ascending,
* vs. descending (reversed).
*/
public static FolderListComparator getDateFirst(boolean ascending) {
return new FolderListComparator(false, ascending);
}
private FolderListComparator(boolean nameFirst, boolean ascending) {
isNameFirst = nameFirst;
isAscending = ascending;
}
@Override
public int compare(DbxFileInfo lhs, DbxFileInfo rhs) {
int rawCmp = rawCompare(lhs, rhs);
return isAscending ? rawCmp : -rawCmp;
}
int rawCompare(DbxFileInfo lhs, DbxFileInfo rhs) {
// Folders are always grouped together, Windows-style.
if (lhs.isFolder != rhs.isFolder) {
return lhs.isFolder ? -1 : 1;
}
// Name and date are next, in the configured order.
if (isNameFirst) {
int cmp = comparePaths(lhs, rhs);
if (0 != cmp) {
return cmp;
}
cmp = compareDates(lhs, rhs);
if (0 != cmp) {
return cmp;
}
} else {
int cmp = compareDates(lhs, rhs);
if (0 != cmp) {
return cmp;
}
cmp = comparePaths(lhs, rhs);
if (0 != cmp) {
return cmp;
}
}
// Use size as final qualifier, though names should be unique in a real
// folder listing.
long longcmp = lhs.size - rhs.size;
if (0 != longcmp) {
return longcmp < 0 ? -1 : 1;
}
return 0;
}
private int comparePaths(DbxFileInfo lhs, DbxFileInfo rhs) {
Collator c = Collator.getInstance(Locale.getDefault());
c.setStrength(Collator.SECONDARY); // Case-insensitive
// TODO: If we want a good ordering of multi-folder listings, we
// may need to do comparison on a per-path-element basis, otherwise
// files can sort unpredictably with respect to subfolders due to the
// ordering of characters with respect to /. This is good enough for
// the listing of a single folder.
return c.compare(lhs.toString(), rhs.toString());
}
private int compareDates(DbxFileInfo lhs, DbxFileInfo rhs) {
return lhs.modifiedTime.compareTo(rhs.modifiedTime);
}
}