001/* 002 * Copyright (c) 2012, the Last.fm Java Project and Committers 003 * All rights reserved. 004 * 005 * Redistribution and use of this software in source and binary forms, with or without modification, are 006 * permitted provided that the following conditions are met: 007 * 008 * - Redistributions of source code must retain the above 009 * copyright notice, this list of conditions and the 010 * following disclaimer. 011 * 012 * - Redistributions in binary form must reproduce the above 013 * copyright notice, this list of conditions and the 014 * following disclaimer in the documentation and/or other 015 * materials provided with the distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 018 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 019 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 020 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 021 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 023 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 024 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 025 */ 026 027package de.umass.lastfm; 028 029import java.text.DateFormat; 030import java.text.ParseException; 031import java.text.SimpleDateFormat; 032import java.util.*; 033 034import de.umass.util.MapUtilities; 035import de.umass.util.StringUtilities; 036import de.umass.xml.DomElement; 037 038/** 039 * Wrapper class for Album related API calls and Album Bean. 040 * 041 * @author Janni Kovacs 042 */ 043public class Album extends MusicEntry { 044 045 static final ItemFactory<Album> FACTORY = new AlbumFactory(); 046 047 private static final DateFormat RELEASE_DATE_FORMAT = new SimpleDateFormat("d MMM yyyy, HH:mm", Locale.ENGLISH); 048 private static final DateFormat RELEASE_DATE_FORMAT_2 = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", 049 Locale.ENGLISH); /* only used in User.getNewReleases() */ 050 051 private String artist; 052 private Date releaseDate; 053 private Collection<Track> tracks; 054 055 private Album(String name, String url, String artist) { 056 super(name, url); 057 this.artist = artist; 058 } 059 060 private Album(String name, String url, String mbid, int playcount, int listeners, boolean streamable, 061 String artist) { 062 super(name, url, mbid, playcount, listeners, streamable); 063 this.artist = artist; 064 } 065 066 public String getArtist() { 067 return artist; 068 } 069 070 public Date getReleaseDate() { 071 return releaseDate; 072 } 073 074 /** 075 * Returns the list of {@link Track}s on this album. This information is only available in 076 * {@link Album#getInfo(String, String, String)} responses. 077 * 078 * @return the list of tracks 079 * @see Album#getInfo(String, String, String) 080 */ 081 public Collection<Track> getTracks() { 082 return tracks; 083 } 084 085 /** 086 * Get the metadata for an album on Last.fm using the album name or a musicbrainz id. 087 * See playlist.fetch on how to get the album playlist. 088 * 089 * @param artist Artist's name 090 * @param albumOrMbid Album name or MBID 091 * @param apiKey The API key 092 * @return Album metadata 093 */ 094 public static Album getInfo(String artist, String albumOrMbid, String apiKey) { 095 return getInfo(artist, albumOrMbid, null, apiKey); 096 } 097 098 /** 099 * Get the metadata for an album on Last.fm using the album name or a musicbrainz id. 100 * See playlist.fetch on how to get the album playlist. 101 * 102 * @param artist Artist's name 103 * @param albumOrMbid Album name or MBID 104 * @param username The username for the context of the request. If supplied, the user's playcount for this album is included in the response. 105 * @param apiKey The API key 106 * @return Album metadata 107 */ 108 public static Album getInfo(String artist, String albumOrMbid, String username, String apiKey) { 109 Map<String, String> params = new HashMap<String, String>(); 110 if (StringUtilities.isMbid(albumOrMbid)) { 111 params.put("mbid", albumOrMbid); 112 } else { 113 params.put("artist", artist); 114 params.put("album", albumOrMbid); 115 } 116 MapUtilities.nullSafePut(params, "username", username); 117 Result result = Caller.getInstance().call("album.getInfo", apiKey, params); 118 return ResponseBuilder.buildItem(result, Album.class); 119 } 120 121 /** 122 * Tag an album using a list of user supplied tags.<br/> 123 * 124 * @param artist The artist name in question 125 * @param album The album name in question 126 * @param tags A comma delimited list of user supplied tags to apply to this album. Accepts a maximum of 10 tags. 127 * @param session The Session instance 128 * @return the Result of the operation 129 * @see Authenticator 130 */ 131 public static Result addTags(String artist, String album, String tags, Session session) { 132 return Caller.getInstance().call("album.addTags", session, "artist", artist, "album", album, "tags", tags); 133 } 134 135 /** 136 * Remove a user's tag from an album. 137 * 138 * @param artist The artist name in question 139 * @param album The album name in question 140 * @param tag A single user tag to remove from this album. 141 * @param session The Session instance 142 * @return the Result of the operation 143 * @see Authenticator 144 */ 145 public static Result removeTag(String artist, String album, String tag, Session session) { 146 return Caller.getInstance().call("album.removeTag", session, "artist", artist, "album", album, "tag", tag); 147 } 148 149 /** 150 * Get the tags applied by an individual user to an album on Last.fm. 151 * 152 * @param artist The artist name in question 153 * @param album The album name in question 154 * @param session A Session instance 155 * @return a list of tags 156 */ 157 public static Collection<String> getTags(String artist, String album, Session session) { 158 Result result = Caller.getInstance().call("album.getTags", session, "artist", artist, "album", album); 159 if (!result.isSuccessful()) 160 return Collections.emptyList(); 161 DomElement element = result.getContentElement(); 162 Collection<String> tags = new ArrayList<String>(); 163 for (DomElement domElement : element.getChildren("tag")) { 164 tags.add(domElement.getChildText("name")); 165 } 166 return tags; 167 } 168 169 /** 170 * Search for an album by name. Returns album matches sorted by relevance. 171 * 172 * @param album The album name in question. 173 * @param apiKey A Last.fm API key. 174 * @return a Collection of matches 175 */ 176 public static Collection<Album> search(String album, String apiKey) { 177 Result result = Caller.getInstance().call("album.search", apiKey, "album", album); 178 DomElement matches = result.getContentElement().getChild("albummatches"); 179 Collection<DomElement> children = matches.getChildren("album"); 180 Collection<Album> albums = new ArrayList<Album>(children.size()); 181 for (DomElement element : children) { 182 albums.add(FACTORY.createItemFromElement(element)); 183 } 184 return albums; 185 } 186 187 /** 188 * Get a list of Buy Links for a particular Album. It is required that you supply either the artist and track params or the mbid param. 189 * 190 * @param artist The artist name in question 191 * @param albumOrMbid Album name or MBID 192 * @param country A country name, as defined by the ISO 3166-1 country names standard 193 * @param apiKey A Last.fm API key 194 * @return a Collection of {@link BuyLink}s 195 */ 196 public static Collection<BuyLink> getBuylinks(String artist, String albumOrMbid, String country, String apiKey) { 197 Map<String, String> params = new HashMap<String, String>(); 198 if (StringUtilities.isMbid(albumOrMbid)) { 199 params.put("mbid", albumOrMbid); 200 } else { 201 params.put("artist", artist); 202 params.put("album", albumOrMbid); 203 } 204 params.put("country", country); 205 Result result = Caller.getInstance().call("album.getBuylinks", apiKey, params); 206 if (!result.isSuccessful()) 207 return Collections.emptyList(); 208 DomElement element = result.getContentElement(); 209 DomElement physicals = element.getChild("physicals"); 210 DomElement downloads = element.getChild("downloads"); 211 Collection<BuyLink> links = new ArrayList<BuyLink>(); 212 for (DomElement e : physicals.getChildren("affiliation")) { 213 links.add(BuyLink.linkFromElement(BuyLink.StoreType.PHYSICAl, e)); 214 } 215 for (DomElement e : downloads.getChildren("affiliation")) { 216 links.add(BuyLink.linkFromElement(BuyLink.StoreType.DIGITAL, e)); 217 } 218 return links; 219 } 220 221 /** 222 * Get the top tags for an album on Last.fm, ordered by popularity. You either have to specify an album and artist name or 223 * an mbid. If you specify an mbid you may pass <code>null</code> for the first parameter. 224 * 225 * @param artist The artist name 226 * @param albumOrMbid Album name or MBID 227 * @param apiKey A Last.fm API key 228 * @return list of top tags 229 */ 230 public static Collection<Tag> getTopTags(String artist, String albumOrMbid, String apiKey) { 231 Map<String, String> params = new HashMap<String, String>(); 232 if (StringUtilities.isMbid(albumOrMbid)) { 233 params.put("mbid", albumOrMbid); 234 } else { 235 params.put("artist", artist); 236 params.put("album", albumOrMbid); 237 } 238 Result result = Caller.getInstance().call("album.getTopTags", apiKey, params); 239 return ResponseBuilder.buildCollection(result, Tag.class); 240 } 241 242 /** 243 * Get shouts for an album. 244 * 245 * @param artist The artist name 246 * @param albumOrMbid The album name or a mausicbrainz id 247 * @param apiKey A Last.fm API key. 248 * @return a page of <code>Shout</code>s 249 */ 250 public static PaginatedResult<Shout> getShouts(String artist, String albumOrMbid, String apiKey) { 251 return getShouts(artist, albumOrMbid, -1, -1, apiKey); 252 } 253 254 /** 255 * Get shouts for an album. 256 * 257 * @param artist The artist name 258 * @param albumOrMbid The album name or a mausicbrainz id 259 * @param page The page number to fetch 260 * @param apiKey A Last.fm API key. 261 * @return a page of <code>Shout</code>s 262 */ 263 public static PaginatedResult<Shout> getShouts(String artist, String albumOrMbid, int page, String apiKey) { 264 return getShouts(artist, albumOrMbid, page, -1, apiKey); 265 } 266 267 /** 268 * Get shouts for an album. 269 * 270 * @param artist The artist name 271 * @param albumOrMbid The album name or a mausicbrainz id 272 * @param page The page number to fetch 273 * @param limit An integer used to limit the number of shouts returned per page or -1 for default 274 * @param apiKey A Last.fm API key. 275 * @return a page of <code>Shout</code>s 276 */ 277 public static PaginatedResult<Shout> getShouts(String artist, String albumOrMbid, int page, int limit, String apiKey) { 278 Map<String, String> params = new HashMap<String, String>(); 279 if (StringUtilities.isMbid(albumOrMbid)) { 280 params.put("mbid", albumOrMbid); 281 } else { 282 params.put("artist", artist); 283 params.put("album", albumOrMbid); 284 } 285 MapUtilities.nullSafePut(params, "limit", limit); 286 MapUtilities.nullSafePut(params, "page", page); 287 Result result = Caller.getInstance().call("album.getShouts", apiKey, params); 288 return ResponseBuilder.buildPaginatedResult(result, Shout.class); 289 } 290 291 private static class AlbumFactory implements ItemFactory<Album> { 292 public Album createItemFromElement(DomElement element) { 293 Album album = new Album(null, null, null); 294 MusicEntry.loadStandardInfo(album, element); 295 if (element.hasChild("artist")) { 296 album.artist = element.getChild("artist").getChildText("name"); 297 if (album.artist == null) 298 album.artist = element.getChildText("artist"); 299 } 300 if (element.hasChild("tracks")) { 301 album.tracks = ResponseBuilder.buildCollection(element.getChild("tracks"), Track.class); 302 } 303 if (element.hasChild("releasedate")) { 304 try { 305 album.releaseDate = RELEASE_DATE_FORMAT.parse(element.getChildText("releasedate")); 306 } catch (ParseException e) { 307 // uh oh 308 } 309 } 310 String releaseDateAttribute = element.getAttribute("releasedate"); 311 if (releaseDateAttribute != null) { 312 try { 313 album.releaseDate = RELEASE_DATE_FORMAT_2.parse(releaseDateAttribute); 314 } catch (ParseException e) { 315 // uh oh 316 } 317 } 318 return album; 319 } 320 } 321}