aboutsummaryrefslogtreecommitdiff
path: root/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java
diff options
context:
space:
mode:
Diffstat (limited to 'subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java')
-rw-r--r--subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java99
1 files changed, 99 insertions, 0 deletions
diff --git a/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java
new file mode 100644
index 00000000..13b5bbbd
--- /dev/null
+++ b/subsonic-main/src/main/java/net/sourceforge/subsonic/domain/MediaFileComparator.java
@@ -0,0 +1,99 @@
+/*
+ This file is part of Subsonic.
+
+ Subsonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Subsonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
+
+ Copyright 2009 (C) Sindre Mehus
+ */
+package net.sourceforge.subsonic.domain;
+
+import java.util.Comparator;
+
+import static net.sourceforge.subsonic.domain.MediaFile.MediaType.DIRECTORY;
+
+/**
+ * Comparator for sorting media files.
+ */
+public class MediaFileComparator implements Comparator<MediaFile> {
+
+ private final boolean sortAlbumsByYear;
+
+ public MediaFileComparator(boolean sortAlbumsByYear) {
+ this.sortAlbumsByYear = sortAlbumsByYear;
+ }
+
+ public int compare(MediaFile a, MediaFile b) {
+
+ // Directories before files.
+ if (a.isFile() && b.isDirectory()) {
+ return 1;
+ }
+ if (a.isDirectory() && b.isFile()) {
+ return -1;
+ }
+
+ // Non-album directories before album directories.
+ if (a.isAlbum() && b.getMediaType() == DIRECTORY) {
+ return 1;
+ }
+ if (a.getMediaType() == DIRECTORY && b.isAlbum()) {
+ return -1;
+ }
+
+ // Sort albums by year
+ if (sortAlbumsByYear && a.isAlbum() && b.isAlbum()) {
+ int i = nullSafeCompare(a.getYear(), b.getYear(), false);
+ if (i != 0) {
+ return i;
+ }
+ }
+
+ if (a.isDirectory() && b.isDirectory()) {
+ return a.getName().compareToIgnoreCase(b.getName());
+ }
+
+ // Compare by disc and track numbers, if present.
+ Integer trackA = getSortableDiscAndTrackNumber(a);
+ Integer trackB = getSortableDiscAndTrackNumber(b);
+ int i = nullSafeCompare(trackA, trackB, false);
+ if (i != 0) {
+ return i;
+ }
+
+ return a.getName().compareToIgnoreCase(b.getName());
+ }
+
+ private <T extends Comparable<T>> int nullSafeCompare(T a, T b, boolean nullIsSmaller) {
+ if (a == null && b == null) {
+ return 0;
+ }
+ if (a == null) {
+ return nullIsSmaller ? -1 : 1;
+ }
+ if (b == null) {
+ return nullIsSmaller ? 1 : -1;
+ }
+ return a.compareTo(b);
+ }
+
+ private Integer getSortableDiscAndTrackNumber(MediaFile file) {
+ if (file.getTrackNumber() == null) {
+ return null;
+ }
+
+ int discNumber = file.getDiscNumber() == null ? 1 : file.getDiscNumber();
+ return discNumber * 1000 + file.getTrackNumber();
+ }
+}
+