package org.limewire.ui.swing.table;
import java.util.Comparator;
import org.limewire.util.CommonUtils;
/**
* Compares two track meta data inputs. Sorts so that null or empty values go to the bottom,
* pure string "gibberish" values go second, and normal numbers or X/Y numbers go first.
*
* <p>Gibberish values are string compared, normal track values are simplified before comparing
* if in complex form where if meta data track is in form X/Y track = X.
*
*/
public class TrackComparator implements Comparator<String> {
/**
* An implementation of compare that groups and orders track descriptors
* according to the rules outlined in this class.
*/
@Override
public int compare(String t1, String t2) {
Object track1 = t1;
Object track2 = t2;
track1 = parseTrackSimple((String)track1);
track2 = parseTrackSimple((String)track2);
if (track1 == null) {
if (track2 == null) {
return 0;
} else {
return -1;
}
}
else {
if (track2 == null) {
return 1;
} else {
return compareConverted(track1, track2);
}
}
}
/**
* Compares non null track data of the simplified Long structure or
* a gibberish string.
*
* <p>Gibberish goes to the bottom and is String sorted.
* <p>Longs go to the top and are Long sorted.
*
* <p>NOTE: track1 and track2 must be instances of String or Long
*/
private static int compareConverted(Object track1, Object track2) {
if (track1 instanceof Long) {
if (track2 instanceof Long) {
return ((Long)track1).compareTo((Long) track2);
} else if (track2 instanceof String) {
return 1;
} else {
throw new IllegalArgumentException("track2 must be an instance of String or Long");
}
} else if (track1 instanceof String) {
if (track2 instanceof Long) {
return -1;
} else if (track2 instanceof String) {
return ((String)track1).compareTo((String) track2);
} else {
throw new IllegalArgumentException("track2 must be an instance of String or Long");
}
} else {
throw new IllegalArgumentException("track1 must be an instance of String or Long");
}
}
/**
* Takes a raw track descriptor string and attempts to simplify it.
*
* <p>If the String is empty it will return null.
* <p>If the String is numeric returns a Long type containing the value.
* <p>If the String is in the format X/Y return a Long type of the numerator X.
* <p>Otherwise simply return the original <b>unmodified</b> String.
*/
private static Object parseTrackSimple(String rawTrack) {
if (rawTrack == null) {
return null;
}
String track = rawTrack.trim();
if ("".equals(track)) {
return null;
}
Long trackSimple = CommonUtils.parseLongNoException(track);
if (trackSimple != null) {
return trackSimple;
}
int slashIndex = track.indexOf('/');
if (slashIndex > -1) {
Long simpleTrack = CommonUtils.parseLongNoException(track.substring(0, slashIndex));
if (simpleTrack != null) {
return simpleTrack;
}
}
return rawTrack;
}
}