View Javadoc

1   /***
2    *     Ambient - A music player for the Android platform
3    Copyright (C) 2007 Martin Vysny
4    
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9    
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14  
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package sk.baka.ambient.collection;
20  
21  import java.util.Collections;
22  import java.util.Comparator;
23  import java.util.List;
24  
25  import android.provider.MediaStore.Audio;
26  
27  import sk.baka.ambient.commons.MiscUtils;
28  
29  /***
30   * Various collection utility methods.
31   * 
32   * @author Martin Vysny
33   */
34  public final class CollectionUtils {
35  	private CollectionUtils() {
36  		throw new Error();
37  	}
38  
39  	/***
40  	 * Sorts given category item list by {@link CategoryItem#name}.
41  	 * 
42  	 * @param items
43  	 *            the items to sort.
44  	 */
45  	public static void sortByKey(final List<CategoryItem> items) {
46  		Collections.sort(items, CATEGORY_KEY_COMPARATOR);
47  	}
48  
49  	private final static Comparator<CategoryItem> CATEGORY_KEY_COMPARATOR = new Comparator<CategoryItem>() {
50  		public int compare(CategoryItem object1, CategoryItem object2) {
51  			return MiscUtils.nullCompare(object1.sortKey, object2.sortKey, true);
52  		}
53  	};
54  
55  	/***
56  	 * Sorts given category item list by {@link CategoryItem#sortKey}.
57  	 * 
58  	 * @param items
59  	 *            the items to sort.
60  	 */
61  	public static void sortByYearKey(final List<CategoryItem> items) {
62  		Collections.sort(items, CATEGORY_YEAR_KEY_COMPARATOR);
63  	}
64  
65  	private final static Comparator<CategoryItem> CATEGORY_YEAR_KEY_COMPARATOR = new Comparator<CategoryItem>() {
66  		public int compare(CategoryItem object1, CategoryItem object2) {
67  			final int result = MiscUtils.nullCompare(object1.year,
68  					object2.year, true);
69  			if (result != 0) {
70  				return result;
71  			}
72  			return MiscUtils.nullCompare(object1.sortKey, object2.sortKey, true);
73  		}
74  	};
75  
76  	/***
77  	 * Sorts given track list by {@link TrackMetadataBean#getDisplayableName()}.
78  	 * 
79  	 * @param tracks
80  	 *            the tracks to sort.
81  	 */
82  	public static void sortByTitle(final List<TrackMetadataBean> tracks) {
83  		Collections.sort(tracks, TRACK_NAME_COMPARATOR);
84  	}
85  
86  	private static final Comparator<TrackMetadataBean> TRACK_NAME_COMPARATOR = new Comparator<TrackMetadataBean>() {
87  		public int compare(TrackMetadataBean object1, TrackMetadataBean object2) {
88  			return object1.getDisplayableName().compareToIgnoreCase(
89  					object2.getDisplayableName());
90  		}
91  	};
92  
93  	/***
94  	 * Orders the tracks by albums, track number and finally by displayable
95  	 * name.
96  	 * 
97  	 * @author Martin Vysny
98  	 */
99  	protected static final class AlbumOrderComparator implements
100 			Comparator<TrackMetadataBean> {
101 		public int compare(TrackMetadataBean object1, TrackMetadataBean object2) {
102 			// compare by albums
103 			int result = MiscUtils.nullCompare(object1.getAlbum(), object2
104 					.getAlbum(), true);
105 			if (result != 0) {
106 				return result;
107 			}
108 			// compare by track number. null < Integer < String
109 			final Object tn1 = parseInt(object1.getTrackNumber());
110 			final Object tn2 = parseInt(object2.getTrackNumber());
111 			result = tn1 == null ? (tn2 == null ? 0 : -1) : (tn2 == null ? 1
112 					: compareTrackNumber(tn1, tn2));
113 			if (result != 0)
114 				return result;
115 			// finally compare by the name
116 			return object1.getDisplayableName().compareToIgnoreCase(
117 					object2.getDisplayableName());
118 		}
119 	}
120 
121 	private static Object parseInt(final String str) {
122 		if (str == null)
123 			return null;
124 		try {
125 			return Integer.valueOf(str);
126 		} catch (NumberFormatException e) {
127 			return str;
128 		}
129 	}
130 
131 	private static int compareTrackNumber(final Object tn1, final Object tn2) {
132 		return (tn1 instanceof Integer) ? (tn2 instanceof Integer ? ((Integer) tn1)
133 				.compareTo((Integer) tn2)
134 				: -1)
135 				: (tn2 instanceof Integer ? 1 : ((String) tn1)
136 						.compareTo((String) tn2));
137 	}
138 
139 	/***
140 	 * Orders the tracks by albums, track number and finally by filenames.
141 	 */
142 	public static final Comparator<TrackMetadataBean> ALBUM_ORDER_COMPARATOR = new AlbumOrderComparator();
143 
144 	/***
145 	 * Sorts the tracks by albums, track number and finally by filenames.
146 	 * 
147 	 * @param playlist
148 	 *            the playlist to sort.
149 	 */
150 	public static void sortByAlbumOrder(final List<TrackMetadataBean> playlist) {
151 		Collections.sort(playlist, ALBUM_ORDER_COMPARATOR);
152 	}
153 	
154 	/***
155 	 * Similar to {@link Audio#keyFor(String)} with a bit relaxed rules: remove
156 	 * leading/trailing spaces, convert everything to lowercase, remove leading
157 	 * "the "
158 	 * 
159 	 * @param name
160 	 *            the name
161 	 * @return key for given name, may be <code>null</code> if the name was
162 	 *         <code>null</code>
163 	 */
164 	public static String keyFor(final String name) {
165 		if (name == null) {
166 			return null;
167 		}
168 		String result = name.trim().toLowerCase();
169 		if (result.startsWith("the")
170 				&& Character.isWhitespace(result.charAt(3))) {
171 			result = result.substring(4);
172 		}
173 		return result;
174 	}
175 }