/* * Jajuk * Copyright (C) The Jajuk Team * http://jajuk.info * * This program 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 2 * of the License, or any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.jajuk.base; import java.io.Serializable; import java.text.DateFormat; import java.util.Comparator; import org.jajuk.util.UtilString; /** * Multi-method track comparator. */ public class TrackComparator implements Comparator<Track>, Serializable { /** Generated serialVersionUID. */ private static final long serialVersionUID = -4735723947400147134L; /** Sorting method. */ private final TrackComparatorType comparatorType; /** * Sorting methods constants. */ public enum TrackComparatorType { /** Compare first based on the genre, then on artist and then on album. */ GENRE_ARTIST_ALBUM, /** Compare based on artist and then album. */ ARTIST_ALBUM, /** Compare only on album. */ ALBUM, /** Compare only on year. */ YEAR_ALBUM, /** Compare only on the discovery date of the album. */ DISCOVERY_ALBUM, /** Compare on the rate and then the album. */ RATE_ALBUM, /** Compare on the number of hits and then on the album. */ HITS_ALBUM, /** Compare on disc number and order of the track in the album. */ ORDER, /** Compare to find identical tracks. */ ALMOST_IDENTICAL } /** The Constant FORMATTER. Used to correctly compare dates. */ private static final DateFormat FORMATTER = UtilString.getAdditionDateFormatter(); /** * Constructor. * * @param comparatorType Specifies the type of comparison that should be done. */ public TrackComparator(TrackComparatorType comparatorType) { this.comparatorType = comparatorType; } /** * Gets the compare string based on the input-track and the type of comparison * that is selected when constructing the comparator. * * @param track The track that should be used for constructing the string. * * @return Hashcode string used to compare two tracks in accordance with the * sorting method */ private String getCompareString(Track track) { String sHashCompare = null; // comparison based on genre, artist, album, name and year to // differentiate 2 tracks with all the same attributes // note we need to use year because in sorted set, we must differentiate // 2 tracks with different years // Genre/artist/album if (comparatorType == TrackComparatorType.GENRE_ARTIST_ALBUM) { sHashCompare = new StringBuilder().append(track.getGenre().getName2()) .append(track.getArtist().getName2()).append(track.getAlbum().getName2()) .append(UtilString.padNumber(track.getOrder(), 5)).append(track.getName()).toString(); }// Artist/album else if (comparatorType == TrackComparatorType.ARTIST_ALBUM) { sHashCompare = new StringBuilder().append(track.getArtist().getName2()) .append(track.getAlbum().getName2()).append(UtilString.padNumber(track.getOrder(), 5)) .append(track.getName()).toString(); } // Album else if (comparatorType == TrackComparatorType.ALBUM) { sHashCompare = new StringBuilder().append(track.getAlbum().getName2()) .append(UtilString.padNumber(track.getOrder(), 5)).append(track.getName()).toString(); } // Year / album if (comparatorType == TrackComparatorType.YEAR_ALBUM) { sHashCompare = new StringBuilder() .append(UtilString.padNumber(999999999 - track.getYear().getValue(), 10)) .append(UtilString.padNumber(track.getOrder(), 5)).append(track.getName()).toString(); } // discovery date / album else if (comparatorType == TrackComparatorType.DISCOVERY_ALBUM) { sHashCompare = new StringBuilder().append(FORMATTER.format(track.getDiscoveryDate())) .append(track.getAlbum().getName2()).append(UtilString.padNumber(track.getOrder(), 5)) .append(track.getName()).toString(); } // Rate / album else if (comparatorType == TrackComparatorType.RATE_ALBUM) { sHashCompare = new StringBuilder() .append(UtilString.padNumber(999999999 - track.getRate(), 10)) .append(UtilString.padNumber(track.getOrder(), 5)).append(track.getName()).toString(); } // Hits / album else if (comparatorType == TrackComparatorType.HITS_ALBUM) { sHashCompare = new StringBuilder() .append(UtilString.padNumber(999999999 - track.getHits(), 10)).append(track.getName()) .toString(); } // Disc number / Order / track name else if (comparatorType == TrackComparatorType.ORDER) { sHashCompare = new StringBuilder().append( UtilString.padNumber(track.getDiscNumber(), 5) + UtilString.padNumber(track.getOrder(), 5) + track.getName()).toString(); } // We want to find identical tracks but using album name, not album id. // We only use set tags, not unknown ones else if (comparatorType == TrackComparatorType.ALMOST_IDENTICAL) { sHashCompare = buildIdenticalTestFootprint(track); } return sHashCompare; } /** * Return a footprint used to find almost-identical track. * * @param track * * @return a footprint used to find almost-identical track */ public String buildIdenticalTestFootprint(Track track) { StringBuilder sb = new StringBuilder(); if (!track.getGenre().seemsUnknown()) { sb.append(track.getGenre().getID()); } if (!track.getArtist().seemsUnknown()) { sb.append(track.getArtist().getID()); } if (!track.getAlbum().seemsUnknown()) { sb.append(track.getAlbum().getName()); } sb.append(track.getName()); if (track.getYear().looksValid()) { sb.append(track.getYear().getValue()); } sb.append(track.getDuration()); sb.append(track.getOrder()); sb.append(track.getType().getID()); sb.append(track.getDiscNumber()); if (!track.getAlbumArtist().seemsUnknown()) { sb.append(track.getAlbumArtist().getName()); } return sb.toString(); } /** * Compares two tracks according to the type selected during constructing of * the comparator.. * * @param track1 The first track for comparison. * @param track2 The second track for comparison. * * @return the value <code>0</code> if track1 is equal to track2; a value less * than <code>0</code> if track1 is less than track2; and a value * greater than <code>0</code> if track1 is greater than track2. */ @Override public int compare(Track track1, Track track2) { String sHashCompare = getCompareString(track1); String sHashCompareOther = getCompareString(track2); return sHashCompare.compareToIgnoreCase(sHashCompareOther); } }