/*
* Copyright (c) 2010, the Last.fm Java Project and Committers
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.umass.lastfm;
import java.util.*;
import de.umass.util.MapUtilities;
import de.umass.xml.DomElement;
/**
* Bean for Chart information. Contains a start date, an end date and a list of entries.
*
* @author Janni Kovacs
*/
public class Chart<T extends MusicEntry> {
private Date from, to;
private Collection<T> entries;
public Chart(Date from, Date to, Collection<T> entries) {
this.from = from;
this.to = to;
this.entries = entries;
}
public Collection<T> getEntries() {
return entries;
}
public Date getFrom() {
return from;
}
public Date getTo() {
return to;
}
/**
* This is an internal method to retrieve Chart data.
*
* @param method The method to call, must be one of the getWeeklyXXXChart methods
* @param sourceType The name of the parameter to get the charts for, either "user", "tag" or "group"
* @param source The username, tag or group to get charts from
* @param target The expected chart type, either "album", "artist" or "track"
* @param from Start date or <code>null</code>
* @param to End date or <code>null</code>
* @param limit The number of chart items to return or -1
* @param apiKey A Last.fm API key.
* @return a Chart
*/
static <T extends MusicEntry> Chart<T> getChart(String method, String sourceType, String source,
String target, String from, String to, int limit,
String apiKey) {
Map<String, String> params = new HashMap<String, String>();
params.put(sourceType, source);
return getChart(method, target, params, from, to, limit, apiKey);
}
/**
* This is an internal method to retrieve Chart data.
*
* @param method The method to call, must be one of the getWeeklyXXXChart methods
* @param params Extra parameters that will be passed to the webservice, e.g. containing user or tag name
* @param target The expected chart type, either "album", "artist" or "track"
* @param from Start date or <code>null</code>
* @param to End date or <code>null</code>
* @param limit The number of chart items to return or -1
* @param apiKey A Last.fm API key.
* @return a Chart
*/
@SuppressWarnings("unchecked")
static <T extends MusicEntry> Chart<T> getChart(String method, String target, Map<String, String> params, String from, String to,
int limit, String apiKey) {
if (from != null && to != null) {
params.put("from", from);
params.put("to", to);
}
MapUtilities.nullSafePut(params, "limit", limit);
Result result = Caller.getInstance().call(method, apiKey, params);
if (!result.isSuccessful())
return null;
DomElement element = result.getContentElement();
Collection<DomElement> children = element.getChildren(target);
Collection collection = new ArrayList(children.size());
boolean targetArtist = "artist".equals(target);
boolean targetTrack = "track".equals(target);
boolean targetAlbum = "album".equals(target);
for (DomElement domElement : children) {
if (targetArtist)
collection.add(ResponseBuilder.buildItem(domElement, Artist.class));
if (targetTrack)
collection.add(ResponseBuilder.buildItem(domElement, Track.class));
if (targetAlbum)
collection.add(ResponseBuilder.buildItem(domElement, Album.class));
}
long fromTime = 0;
long toTime = 0;
// workaround for geo.getMetroXXX methods, since they don't have from & to attributes if no dates were given upon calling
if (element.hasAttribute("from")) {
fromTime = 1000 * Long.parseLong(element.getAttribute("from"));
toTime = 1000 * Long.parseLong(element.getAttribute("to"));
}
return new Chart<T>(new Date(fromTime), new Date(toTime), collection);
}
/**
* This is an internal method to get a list of available charts.
*
* @param methodName The name of the method to be called, e.g. <code>user.getWeeklyChartList</code>
* @param paramName The name of the parameter which is passed to the specified method, e.g. <code>user</code>
* @param paramValue The value of the parameter which is passed to the specified method, e.g. the user name
* @param apiKey A Last.fm API key.
* @return a list of available charts as a Map
*/
static LinkedHashMap<String, String> getWeeklyChartList(String methodName, String paramName, String paramValue, String apiKey) {
Result result = Caller.getInstance().call(methodName, apiKey, paramName, paramValue);
if (!result.isSuccessful())
return new LinkedHashMap<String, String>(0);
DomElement element = result.getContentElement();
LinkedHashMap<String, String> list = new LinkedHashMap<String, String>();
for (DomElement domElement : element.getChildren("chart")) {
list.put(domElement.getAttribute("from"), domElement.getAttribute("to"));
}
return list;
}
/**
* This is an internal method to get a list of available charts.
*
* @param sourceType The name of the parameter to get the charts for, either "user", "tag" or "group"
* @param source The username, tag or group to get charts from
* @param apiKey A Last.fm API key.
* @return a list of available charts as a Collection of Charts
*/
@SuppressWarnings("unchecked")
static Collection<Chart> getWeeklyChartListAsCharts(String sourceType, String source, String apiKey) {
Result result = Caller.getInstance().call(sourceType + ".getWeeklyChartList", apiKey, sourceType, source);
if (!result.isSuccessful())
return Collections.emptyList();
DomElement element = result.getContentElement();
List<Chart> list = new ArrayList<Chart>();
for (DomElement domElement : element.getChildren("chart")) {
long fromTime = 1000 * Long.parseLong(domElement.getAttribute("from"));
long toTime = 1000 * Long.parseLong(domElement.getAttribute("to"));
list.add(new Chart(new Date(fromTime), new Date(toTime), null));
}
return list;
}
/**
* Get the top artists chart.
*
* @param apiKey A Last.fm API key
* @return Top artists chart
*/
public static PaginatedResult<Artist> getTopArtists(String apiKey) {
return getTopArtists(1, apiKey);
}
/**
* Get the top artists chart.
*
* @param page The page to fetch
* @param apiKey A Last.fm API key
* @return Top artists chart
*/
public static PaginatedResult<Artist> getTopArtists(int page, String apiKey) {
Result result = Caller.getInstance().call("chart.getTopArtists", apiKey, "page", String.valueOf(page));
return ResponseBuilder.buildPaginatedResult(result, Artist.class);
}
/**
* Get the top tags chart.
*
* @param apiKey A Last.fm API key
* @return Top tags chart
*/
public static PaginatedResult<Tag> getTopTags(String apiKey) {
return getTopTags(1, apiKey);
}
/**
* Get the top tags chart.
*
* @param page The page to fetch
* @param apiKey A Last.fm API key
* @return Top tags chart
*/
public static PaginatedResult<Tag> getTopTags(int page, String apiKey) {
Result result = Caller.getInstance().call("chart.getTopTags", apiKey, "page", String.valueOf(page));
return ResponseBuilder.buildPaginatedResult(result, Tag.class);
}
/**
* Get the top tracks chart.
*
* @param apiKey A Last.fm API key
* @return Top tracks chart
*/
public static PaginatedResult<Track> getTopTracks(String apiKey) {
return getTopTracks(1, apiKey);
}
/**
* Get the top tracks chart.
*
* @param page The page to fetch
* @param apiKey A Last.fm API key
* @return Top tracks chart
*/
public static PaginatedResult<Track> getTopTracks(int page, String apiKey) {
Result result = Caller.getInstance().call("chart.getTopTracks", apiKey, "page", String.valueOf(page));
return ResponseBuilder.buildPaginatedResult(result, Track.class);
}
/**
* Get the most loved tracks chart.
*
* @param apiKey A Last.fm API key
* @return Most loved tracks chart
*/
public static PaginatedResult<Track> getLovedTracks(String apiKey) {
return getLovedTracks(1, apiKey);
}
/**
* Get the most loved tracks chart.
*
* @param page The page to fetch
* @param apiKey A Last.fm API key
* @return Most loved tracks chart
*/
public static PaginatedResult<Track> getLovedTracks(int page, String apiKey) {
Result result = Caller.getInstance().call("chart.getLovedTracks", apiKey, "page", String.valueOf(page));
return ResponseBuilder.buildPaginatedResult(result, Track.class);
}
/**
* Get the hyped tracks chart.
*
* @param apiKey A Last.fm API key
* @return Hyped tracks chart
*/
public static PaginatedResult<Track> getHypedTracks(String apiKey) {
return getHypedTracks(1, apiKey);
}
/**
* Get the hyped tracks chart.
*
* @param page The page to fetch
* @param apiKey A Last.fm API key
* @return Hyped tracks chart
*/
public static PaginatedResult<Track> getHypedTracks(int page, String apiKey) {
Result result = Caller.getInstance().call("chart.getHypedTracks", apiKey, "page", String.valueOf(page));
return ResponseBuilder.buildPaginatedResult(result, Track.class);
}
/**
* Get the hyped artists chart.
*
* @param apiKey A Last.fm API key
* @return Hyped artists chart
*/
public static PaginatedResult<Artist> getHypedArtists(String apiKey) {
return getHypedArtists(1, apiKey);
}
/**
* Get the hyped artists chart.
*
* @param page The page to fetch
* @param apiKey A Last.fm API key
* @return Hyped artists chart
*/
public static PaginatedResult<Artist> getHypedArtists(int page, String apiKey) {
Result result = Caller.getInstance().call("chart.getHypedArtists", apiKey, "page", String.valueOf(page));
return ResponseBuilder.buildPaginatedResult(result, Artist.class);
}
}