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.util.*; 030 031import de.umass.util.MapUtilities; 032import de.umass.xml.DomElement; 033 034/** 035 * Bean for Chart information. Contains a start date, an end date and a list of entries. 036 * 037 * @author Janni Kovacs 038 */ 039public class Chart<T extends MusicEntry> { 040 041 private Date from, to; 042 private Collection<T> entries; 043 044 public Chart(Date from, Date to, Collection<T> entries) { 045 this.from = from; 046 this.to = to; 047 this.entries = entries; 048 } 049 050 public Collection<T> getEntries() { 051 return entries; 052 } 053 054 public Date getFrom() { 055 return from; 056 } 057 058 public Date getTo() { 059 return to; 060 } 061 062 /** 063 * This is an internal method to retrieve Chart data. 064 * 065 * @param method The method to call, must be one of the getWeeklyXXXChart methods 066 * @param sourceType The name of the parameter to get the charts for, either "user", "tag" or "group" 067 * @param source The username, tag or group to get charts from 068 * @param target The expected chart type, either "album", "artist" or "track" 069 * @param from Start date or <code>null</code> 070 * @param to End date or <code>null</code> 071 * @param limit The number of chart items to return or -1 072 * @param apiKey A Last.fm API key. 073 * @return a Chart 074 */ 075 static <T extends MusicEntry> Chart<T> getChart(String method, String sourceType, String source, 076 String target, String from, String to, int limit, 077 String apiKey) { 078 Map<String, String> params = new HashMap<String, String>(); 079 params.put(sourceType, source); 080 return getChart(method, target, params, from, to, limit, apiKey); 081 } 082 083 /** 084 * This is an internal method to retrieve Chart data. 085 * 086 * @param method The method to call, must be one of the getWeeklyXXXChart methods 087 * @param params Extra parameters that will be passed to the webservice, e.g. containing user or tag name 088 * @param target The expected chart type, either "album", "artist" or "track" 089 * @param from Start date or <code>null</code> 090 * @param to End date or <code>null</code> 091 * @param limit The number of chart items to return or -1 092 * @param apiKey A Last.fm API key. 093 * @return a Chart 094 */ 095 @SuppressWarnings("unchecked") 096 static <T extends MusicEntry> Chart<T> getChart(String method, String target, Map<String, String> params, String from, String to, 097 int limit, String apiKey) { 098 if (from != null && to != null) { 099 params.put("from", from); 100 params.put("to", to); 101 } 102 MapUtilities.nullSafePut(params, "limit", limit); 103 Result result = Caller.getInstance().call(method, apiKey, params); 104 if (!result.isSuccessful()) 105 return null; 106 DomElement element = result.getContentElement(); 107 Collection<DomElement> children = element.getChildren(target); 108 Collection collection = new ArrayList(children.size()); 109 boolean targetArtist = "artist".equals(target); 110 boolean targetTrack = "track".equals(target); 111 boolean targetAlbum = "album".equals(target); 112 for (DomElement domElement : children) { 113 if (targetArtist) 114 collection.add(ResponseBuilder.buildItem(domElement, Artist.class)); 115 if (targetTrack) 116 collection.add(ResponseBuilder.buildItem(domElement, Track.class)); 117 if (targetAlbum) 118 collection.add(ResponseBuilder.buildItem(domElement, Album.class)); 119 } 120 long fromTime = 0; 121 long toTime = 0; 122 // workaround for geo.getMetroXXX methods, since they don't have from & to attributes if no dates were given upon calling 123 if (element.hasAttribute("from")) { 124 fromTime = 1000 * Long.parseLong(element.getAttribute("from")); 125 toTime = 1000 * Long.parseLong(element.getAttribute("to")); 126 } 127 return new Chart<T>(new Date(fromTime), new Date(toTime), collection); 128 } 129 130 /** 131 * This is an internal method to get a list of available charts. 132 * 133 * @param methodName The name of the method to be called, e.g. <code>user.getWeeklyChartList</code> 134 * @param paramName The name of the parameter which is passed to the specified method, e.g. <code>user</code> 135 * @param paramValue The value of the parameter which is passed to the specified method, e.g. the user name 136 * @param apiKey A Last.fm API key. 137 * @return a list of available charts as a Map 138 */ 139 static LinkedHashMap<String, String> getWeeklyChartList(String methodName, String paramName, String paramValue, String apiKey) { 140 Result result = Caller.getInstance().call(methodName, apiKey, paramName, paramValue); 141 if (!result.isSuccessful()) 142 return new LinkedHashMap<String, String>(0); 143 DomElement element = result.getContentElement(); 144 LinkedHashMap<String, String> list = new LinkedHashMap<String, String>(); 145 for (DomElement domElement : element.getChildren("chart")) { 146 list.put(domElement.getAttribute("from"), domElement.getAttribute("to")); 147 } 148 return list; 149 } 150 151 /** 152 * This is an internal method to get a list of available charts. 153 * 154 * @param sourceType The name of the parameter to get the charts for, either "user", "tag" or "group" 155 * @param source The username, tag or group to get charts from 156 * @param apiKey A Last.fm API key. 157 * @return a list of available charts as a Collection of Charts 158 */ 159 @SuppressWarnings("unchecked") 160 static Collection<Chart> getWeeklyChartListAsCharts(String sourceType, String source, String apiKey) { 161 Result result = Caller.getInstance().call(sourceType + ".getWeeklyChartList", apiKey, sourceType, source); 162 if (!result.isSuccessful()) 163 return Collections.emptyList(); 164 DomElement element = result.getContentElement(); 165 List<Chart> list = new ArrayList<Chart>(); 166 for (DomElement domElement : element.getChildren("chart")) { 167 long fromTime = 1000 * Long.parseLong(domElement.getAttribute("from")); 168 long toTime = 1000 * Long.parseLong(domElement.getAttribute("to")); 169 list.add(new Chart(new Date(fromTime), new Date(toTime), null)); 170 } 171 return list; 172 } 173 174 /** 175 * Get the top artists chart. 176 * 177 * @param apiKey A Last.fm API key 178 * @return Top artists chart 179 */ 180 public static PaginatedResult<Artist> getTopArtists(String apiKey) { 181 return getTopArtists(1, apiKey); 182 } 183 184 /** 185 * Get the top artists chart. 186 * 187 * @param page The page to fetch 188 * @param apiKey A Last.fm API key 189 * @return Top artists chart 190 */ 191 public static PaginatedResult<Artist> getTopArtists(int page, String apiKey) { 192 Result result = Caller.getInstance().call("chart.getTopArtists", apiKey, "page", String.valueOf(page)); 193 return ResponseBuilder.buildPaginatedResult(result, Artist.class); 194 } 195 196 /** 197 * Get the top tags chart. 198 * 199 * @param apiKey A Last.fm API key 200 * @return Top tags chart 201 */ 202 public static PaginatedResult<Tag> getTopTags(String apiKey) { 203 return getTopTags(1, apiKey); 204 } 205 206 /** 207 * Get the top tags chart. 208 * 209 * @param page The page to fetch 210 * @param apiKey A Last.fm API key 211 * @return Top tags chart 212 */ 213 public static PaginatedResult<Tag> getTopTags(int page, String apiKey) { 214 Result result = Caller.getInstance().call("chart.getTopTags", apiKey, "page", String.valueOf(page)); 215 return ResponseBuilder.buildPaginatedResult(result, Tag.class); 216 } 217 218 /** 219 * Get the top tracks chart. 220 * 221 * @param apiKey A Last.fm API key 222 * @return Top tracks chart 223 */ 224 public static PaginatedResult<Track> getTopTracks(String apiKey) { 225 return getTopTracks(1, apiKey); 226 } 227 228 /** 229 * Get the top tracks chart. 230 * 231 * @param page The page to fetch 232 * @param apiKey A Last.fm API key 233 * @return Top tracks chart 234 */ 235 public static PaginatedResult<Track> getTopTracks(int page, String apiKey) { 236 Result result = Caller.getInstance().call("chart.getTopTracks", apiKey, "page", String.valueOf(page)); 237 return ResponseBuilder.buildPaginatedResult(result, Track.class); 238 } 239 240 /** 241 * Get the most loved tracks chart. 242 * 243 * @param apiKey A Last.fm API key 244 * @return Most loved tracks chart 245 */ 246 public static PaginatedResult<Track> getLovedTracks(String apiKey) { 247 return getLovedTracks(1, apiKey); 248 } 249 250 /** 251 * Get the most loved tracks chart. 252 * 253 * @param page The page to fetch 254 * @param apiKey A Last.fm API key 255 * @return Most loved tracks chart 256 */ 257 public static PaginatedResult<Track> getLovedTracks(int page, String apiKey) { 258 Result result = Caller.getInstance().call("chart.getLovedTracks", apiKey, "page", String.valueOf(page)); 259 return ResponseBuilder.buildPaginatedResult(result, Track.class); 260 } 261 262 /** 263 * Get the hyped tracks chart. 264 * 265 * @param apiKey A Last.fm API key 266 * @return Hyped tracks chart 267 */ 268 public static PaginatedResult<Track> getHypedTracks(String apiKey) { 269 return getHypedTracks(1, apiKey); 270 } 271 272 /** 273 * Get the hyped tracks chart. 274 * 275 * @param page The page to fetch 276 * @param apiKey A Last.fm API key 277 * @return Hyped tracks chart 278 */ 279 public static PaginatedResult<Track> getHypedTracks(int page, String apiKey) { 280 Result result = Caller.getInstance().call("chart.getHypedTracks", apiKey, "page", String.valueOf(page)); 281 return ResponseBuilder.buildPaginatedResult(result, Track.class); 282 } 283 284 /** 285 * Get the hyped artists chart. 286 * 287 * @param apiKey A Last.fm API key 288 * @return Hyped artists chart 289 */ 290 public static PaginatedResult<Artist> getHypedArtists(String apiKey) { 291 return getHypedArtists(1, apiKey); 292 } 293 294 /** 295 * Get the hyped artists chart. 296 * 297 * @param page The page to fetch 298 * @param apiKey A Last.fm API key 299 * @return Hyped artists chart 300 */ 301 public static PaginatedResult<Artist> getHypedArtists(int page, String apiKey) { 302 Result result = Caller.getInstance().call("chart.getHypedArtists", apiKey, "page", String.valueOf(page)); 303 return ResponseBuilder.buildPaginatedResult(result, Artist.class); 304 } 305}