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  package sk.baka.ambient.playlist;
19  
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.Comparator;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Random;
27  
28  import sk.baka.ambient.collection.CollectionUtils;
29  import sk.baka.ambient.collection.TrackMetadataBean;
30  import sk.baka.ambient.commons.MiscUtils;
31  
32  /***
33   * Utility methods.
34   * 
35   * @author Martin Vysny
36   */
37  public final class Utils {
38  	/***
39  	 * Prevent instantiation
40  	 */
41  	private Utils() {
42  		super();
43  	}
44  
45  	/***
46  	 * Orders the tracks by albums, track number and finally by filenames.
47  	 */
48  	public static final Comparator<PlaylistItem> PLAYLIST_ALBUM_ORDER_COMPARATOR = new Comparator<PlaylistItem>() {
49  		public int compare(PlaylistItem object1, PlaylistItem object2) {
50  			return CollectionUtils.ALBUM_ORDER_COMPARATOR.compare(object1
51  					.getTrack(), object2.getTrack());
52  		}
53  	};
54  
55  	/***
56  	 * Sorts the tracks by albums, track number and finally by filenames.
57  	 * 
58  	 * @param playlist
59  	 *            the playlist to sort.
60  	 */
61  	public static void sortPlaylistByAlbumOrder(
62  			final List<PlaylistItem> playlist) {
63  		Collections.sort(playlist, PLAYLIST_ALBUM_ORDER_COMPARATOR);
64  	}
65  
66  	/***
67  	 * Retrieves a map of album names to a list of tracks in that particular
68  	 * album.
69  	 * 
70  	 * @param playlist
71  	 *            retrieve the map from this playlist.
72  	 * @return map from album name to its tracks. The track ordering is the same
73  	 *         as in the playlist. Same tracks may appear multiple times in the
74  	 *         album if they appeared multiple times in the original playlist.
75  	 */
76  	public static Map<String, List<PlaylistItem>> getAlbumsFromPlaylist(
77  			final List<PlaylistItem> playlist) {
78  		final Map<String, List<PlaylistItem>> result = new HashMap<String, List<PlaylistItem>>();
79  		for (final PlaylistItem item : playlist) {
80  			List<PlaylistItem> albumTracklist = result.get(item.getTrack()
81  					.getAlbum());
82  			if (albumTracklist == null) {
83  				albumTracklist = new ArrayList<PlaylistItem>();
84  				result.put(item.getTrack().getAlbum(), albumTracklist);
85  			}
86  			albumTracklist.add(item);
87  		}
88  		return result;
89  	}
90  
91  	/***
92  	 * Adds given track to the album map structure.
93  	 * 
94  	 * @param albumMap
95  	 *            the map to modify, must not be <code>null</code>
96  	 * @param item
97  	 *            the track to add, must not be <code>null</code>
98  	 */
99  	public static void addToAlbumMap(
100 			final Map<String, List<TrackMetadataBean>> albumMap,
101 			final TrackMetadataBean item) {
102 		List<TrackMetadataBean> albumTracklist = albumMap.get(item.getAlbum());
103 		if (albumTracklist == null) {
104 			albumTracklist = new ArrayList<TrackMetadataBean>();
105 			albumMap.put(item.getAlbum(), albumTracklist);
106 		}
107 		albumTracklist.add(item);
108 	}
109 
110 	/***
111 	 * Removes given track from the album map structure.
112 	 * 
113 	 * @param albumMap
114 	 *            the map to modify, must not be <code>null</code>
115 	 * @param item
116 	 *            the track to remove, must not be <code>null</code>
117 	 */
118 	public static void removeFromAlbumMap(
119 			final Map<String, List<TrackMetadataBean>> albumMap,
120 			final TrackMetadataBean item) {
121 		List<TrackMetadataBean> albumTracklist = albumMap.get(item.getAlbum());
122 		if (albumTracklist == null) {
123 			return;
124 		}
125 		albumTracklist.remove(item);
126 		if (albumTracklist.isEmpty()) {
127 			albumMap.remove(item.getAlbum());
128 		}
129 	}
130 
131 	/***
132 	 * Retrieves a map of album names to a list of tracks in that particular
133 	 * album.
134 	 * 
135 	 * @param playlist
136 	 *            retrieve the map from this playlist.
137 	 * @param sort
138 	 *            if <code>true</code> then all albums tracks will be sorted.
139 	 * @return map from album name to its tracks. The track ordering is the same
140 	 *         as in the playlist unless sort is required. Same tracks may
141 	 *         appear multiple times in the album if they appeared multiple
142 	 *         times in the original playlist.
143 	 */
144 	public static Map<String, List<TrackMetadataBean>> getAlbumsFromBeans(
145 			final List<TrackMetadataBean> playlist, boolean sort) {
146 		final Map<String, List<TrackMetadataBean>> result = new HashMap<String, List<TrackMetadataBean>>();
147 		for (final TrackMetadataBean item : playlist) {
148 			addToAlbumMap(result, item);
149 		}
150 		if (sort) {
151 			for (List<TrackMetadataBean> album : result.values()) {
152 				CollectionUtils.sortByAlbumOrder(album);
153 			}
154 		}
155 		return result;
156 	}
157 
158 	/***
159 	 * Returns {@link List#subList(int, int)} from given list with all items
160 	 * having given album.
161 	 * 
162 	 * @param playlist
163 	 *            the playlist
164 	 * @param album
165 	 *            the album to search for
166 	 * @return first continuous sublist from given list with given album name.
167 	 *         Returns empty list from the end of the playlist if no album
168 	 *         match.
169 	 */
170 	public static List<PlaylistItem> getAlbumSublist(
171 			final List<PlaylistItem> playlist, final String album) {
172 		int from;
173 		for (from = 0; from < playlist.size(); from++) {
174 			if (MiscUtils.nullCompare(playlist.get(from).getTrack().getAlbum(),
175 					album, true) == 0)
176 				break;
177 		}
178 		int to;
179 		for (to = from; to < playlist.size(); to++) {
180 			if (MiscUtils.nullCompare(playlist.get(to).getTrack().getAlbum(),
181 					album, true) != 0)
182 				break;
183 		}
184 		return playlist.subList(from, to);
185 	}
186 
187 	/***
188 	 * Creates new list, having all items with given album.
189 	 * 
190 	 * @param playlist
191 	 *            the playlist
192 	 * @param album
193 	 *            the album to search for
194 	 * @return all items from given playlist in the playlist ordering. Never
195 	 *         <code>null</code>, may be empty.
196 	 */
197 	public static List<PlaylistItem> filterOnAlbum(
198 			final List<PlaylistItem> playlist, final String album) {
199 		final List<PlaylistItem> result = new ArrayList<PlaylistItem>();
200 		for (final PlaylistItem item : playlist) {
201 			if (MiscUtils.nullEquals(album, item.track.getAlbum())) {
202 				result.add(item);
203 			}
204 		}
205 		return result;
206 	}
207 
208 	/***
209 	 * The random number generator.
210 	 */
211 	public final static Random RANDOM = new Random();
212 
213 	/***
214 	 * Modifies the playlist by changing all {@link PlaylistItem} locations.
215 	 * 
216 	 * @param locationMap
217 	 *            maps old locations to new locations.
218 	 * @param playlist
219 	 *            the playlist
220 	 */
221 	public static void replaceLocations(final List<PlaylistItem> playlist,
222 			final Map<String, String> locationMap) {
223 		for (final PlaylistItem item: playlist) {
224 			final String newLocation = locationMap.get(item.getTrack()
225 					.getLocation());
226 			if (newLocation == null) {
227 				continue;
228 			}
229 			final TrackMetadataBean track = new TrackMetadataBean.Builder()
230 					.getData(item.getTrack()).setLocation(newLocation).build(
231 							item.getTrack().getTrackId());
232 			item.track = track;
233 		}
234 	}
235 }