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.util.StringUtilities; 033import de.umass.xml.DomElement; 034 035/** 036 * Provides nothing more than a namespace for the API methods starting with geo. 037 * 038 * @author Janni Kovacs 039 */ 040public class Geo { 041 042 /** 043 * This inner class represents a Metro, which is composed of its name and the name of its country. 044 * 045 * @see Geo#getMetros(String, String) 046 */ 047 public static class Metro { 048 private String name; 049 private String country; 050 051 public Metro(String name, String country) { 052 this.name = name; 053 this.country = country; 054 } 055 056 public String getName() { 057 return name; 058 } 059 060 public String getCountry() { 061 return country; 062 } 063 } 064 065 private Geo() { 066 } 067 068 /** 069 * Get all events in a specific location by country or city name.<br/> This method returns <em>all</em> events by subsequently calling 070 * {@link #getEvents(String, String, int, String)} and concatenating the single results into one list.<br/> Pay attention if you use this 071 * method as it may produce a lot of network traffic and therefore may consume a long time. 072 * 073 * @param location Specifies a location to retrieve events for 074 * @param distance Find events within a specified radius (in kilometres) 075 * @param apiKey A Last.fm API key. 076 * @return a list containing all events 077 */ 078 public static Collection<Event> getAllEvents(String location, String distance, String apiKey) { 079 Collection<Event> events = null; 080 int page = 1, total; 081 do { 082 PaginatedResult<Event> result = getEvents(location, distance, page, apiKey); 083 total = result.getTotalPages(); 084 Collection<Event> pageResults = result.getPageResults(); 085 if (events == null) { 086 // events is initialized here to initialize it with the right size and avoid array copying later on 087 events = new ArrayList<Event>(total * pageResults.size()); 088 } 089 for (Event artist : pageResults) { 090 events.add(artist); 091 } 092 page++; 093 } while (page <= total); 094 return events; 095 } 096 097 /** 098 * Get all events in a specific location by country or city name.<br/> This method only returns the first page of a possibly paginated 099 * result. To retrieve all pages get the total number of pages via {@link de.umass.lastfm.PaginatedResult#getTotalPages()} and subsequently 100 * call {@link #getEvents(String, String, int, String)} with the successive page numbers. 101 * 102 * @param location Specifies a location to retrieve events for 103 * @param distance Find events within a specified radius (in kilometres) 104 * @param apiKey A Last.fm API key. 105 * @return a {@link PaginatedResult} containing a list of events 106 */ 107 public static PaginatedResult<Event> getEvents(String location, String distance, String apiKey) { 108 return getEvents(location, distance, 1, apiKey); 109 } 110 111 /** 112 * Get all events in a specific location by country or city name.<br/> This method only returns the specified page of a paginated result. 113 * 114 * @param location Specifies a location to retrieve events for 115 * @param distance Find events within a specified radius (in kilometres) 116 * @param page A page number for pagination 117 * @param apiKey A Last.fm API key. 118 * @return a {@link PaginatedResult} containing a list of events 119 */ 120 public static PaginatedResult<Event> getEvents(String location, String distance, int page, String apiKey) { 121 return getEvents(location, distance, page, -1, apiKey); 122 } 123 124 public static PaginatedResult<Event> getEvents(String location, String distance, int page, int limit, String apiKey) { 125 Map<String, String> params = new HashMap<String, String>(); 126 params.put("page", String.valueOf(page)); 127 MapUtilities.nullSafePut(params, "location", location); 128 MapUtilities.nullSafePut(params, "distance", distance); 129 MapUtilities.nullSafePut(params, "limit", limit); 130 Result result = Caller.getInstance().call("geo.getEvents", apiKey, params); 131 return ResponseBuilder.buildPaginatedResult(result, Event.class); 132 } 133 134 /** 135 * Get all events in a specific location by latitude/longitude.<br/> This method only returns the specified page of a paginated result. 136 * 137 * @param latitude Latitude 138 * @param longitude Longitude 139 * @param page A page number for pagination 140 * @param apiKey A Last.fm API key. 141 * @return a {@link PaginatedResult} containing a list of events 142 */ 143 public static PaginatedResult<Event> getEvents(double latitude, double longitude, int page, String apiKey) { 144 return getEvents(latitude, longitude, page, -1, apiKey); 145 } 146 147 public static PaginatedResult<Event> getEvents(double latitude, double longitude, int page, int limit, String apiKey) { 148 Map<String, String> params = new HashMap<String, String>(); 149 params.put("page", String.valueOf(page)); 150 params.put("lat", String.valueOf(latitude)); 151 params.put("long", String.valueOf(longitude)); 152 MapUtilities.nullSafePut(params, "limit", limit); 153 Result result = Caller.getInstance().call("geo.getEvents", apiKey, params); 154 return ResponseBuilder.buildPaginatedResult(result, Event.class); 155 } 156 157 public static PaginatedResult<Event> getEvents(double latitude, double longitude, String distance, String apiKey) { 158 return getEvents(latitude, longitude, distance, -1, -1, apiKey); 159 } 160 161 /** 162 * Get all events within the specified distance of the location specified by latitude/longitude.<br/> 163 * This method only returns the specified page of a paginated result. 164 * 165 * @param latitude Latitude 166 * @param longitude Longitude 167 * @param distance Find events within a specified radius (in kilometres) 168 * @param page A page number for pagination 169 * @param limit The maximum number of items returned per page 170 * @param apiKey A Last.fm API key. 171 * @return a {@link PaginatedResult} containing a list of events 172 */ 173 public static PaginatedResult<Event> getEvents(double latitude, double longitude, String distance, int page, int limit, String apiKey) { 174 Map<String, String> params = new HashMap<String, String>(); 175 params.put("lat", String.valueOf(latitude)); 176 params.put("long", String.valueOf(longitude)); 177 params.put("distance", distance); 178 MapUtilities.nullSafePut(params, "page", page); 179 MapUtilities.nullSafePut(params, "limit", limit); 180 Result result = Caller.getInstance().call("geo.getEvents", apiKey, params); 181 return ResponseBuilder.buildPaginatedResult(result, Event.class); 182 } 183 184 /** 185 * Get the most popular artists on Last.fm by country 186 * 187 * @param country A country name, as defined by the ISO 3166-1 country names standard 188 * @param apiKey A Last.fm API key. 189 * @return list of Artists 190 */ 191 public static Collection<Artist> getTopArtists(String country, String apiKey) { 192 Result result = Caller.getInstance().call("geo.getTopArtists", apiKey, "country", country); 193 return ResponseBuilder.buildCollection(result, Artist.class); 194 } 195 196 /** 197 * Get the most popular tracks on Last.fm by country 198 * 199 * @param country A country name, as defined by the ISO 3166-1 country names standard 200 * @param apiKey A Last.fm API key. 201 * @return a list of Tracks 202 */ 203 public static Collection<Track> getTopTracks(String country, String apiKey) { 204 Result result = Caller.getInstance().call("geo.getTopTracks", apiKey, "country", country); 205 return ResponseBuilder.buildCollection(result, Track.class); 206 } 207 208 /** 209 * Get a list of valid countries and {@link Metro}s for use in the other webservices. 210 * 211 * @param apiKey A Last.fm API key 212 * @return a List of {@link Metro}s 213 */ 214 public static Collection<Metro> getMetros(String apiKey) { 215 return getMetros(null, apiKey); 216 } 217 218 /** 219 * Get a list of valid countries and {@link Metro}s for use in the other webservices. 220 * 221 * @param country Optionally restrict the results to those Metros from a particular country, as defined by the ISO 3166-1 country names 222 * standard 223 * @param apiKey A Last.fm API key 224 * @return a List of {@link Metro}s 225 */ 226 public static Collection<Metro> getMetros(String country, String apiKey) { 227 Map<String, String> params = new HashMap<String, String>(); 228 MapUtilities.nullSafePut(params, "country", country); 229 Result result = Caller.getInstance().call("geo.getMetros", apiKey, params); 230 if (!result.isSuccessful()) 231 return Collections.emptyList(); 232 Collection<DomElement> children = result.getContentElement().getChildren("metro"); 233 Collection<Metro> metros = new ArrayList<Metro>(children.size()); 234 for (DomElement child : children) { 235 metros.add(new Metro(child.getChildText("name"), child.getChildText("country"))); 236 } 237 return metros; 238 } 239 240 /** 241 * Get a list of available chart periods for this metro, expressed as date ranges which can be sent to the chart services. 242 * 243 * @param metro The name of the metro, or <code>null</code> 244 * @param apiKey A Last.fm API key 245 * @return a list of available charts as a Map 246 */ 247 public static LinkedHashMap<String, String> getMetroWeeklyChartList(String metro, String apiKey) { 248 return Chart.getWeeklyChartList("geo.getMetroWeeklyChartList", "metro", metro, apiKey); 249 } 250 251 public static Chart<Artist> getMetroArtistChart(String country, String metro, String apiKey) { 252 return getMetroArtistChart(country, metro, null, null, apiKey); 253 } 254 255 public static Chart<Artist> getMetroArtistChart(Metro metro, String start, String end, String apiKey) { 256 return getMetroArtistChart(metro.getCountry(), metro.getName(), start, end, apiKey); 257 } 258 259 public static Chart<Artist> getMetroArtistChart(String country, String metro, String start, String end, String apiKey) { 260 return Chart.getChart("geo.getMetroArtistChart", "artist", StringUtilities.map("country", country, "metro", metro), start, end, -1, 261 apiKey); 262 } 263 264 public static Chart<Track> getMetroTrackChart(String country, String metro, String apiKey) { 265 return getMetroTrackChart(country, metro, null, null, apiKey); 266 } 267 268 public static Chart<Track> getMetroTrackChart(Metro metro, String start, String end, String apiKey) { 269 return getMetroTrackChart(metro.getCountry(), metro.getName(), start, end, apiKey); 270 } 271 272 public static Chart<Track> getMetroTrackChart(String country, String metro, String start, String end, String apiKey) { 273 return Chart.getChart("geo.getMetroTrackChart", "track", StringUtilities.map("country", country, "metro", metro), start, end, -1, 274 apiKey); 275 } 276 277 public static Chart<Artist> getMetroHypeArtistChart(String country, String metro, String apiKey) { 278 return getMetroHypeArtistChart(country, metro, null, null, apiKey); 279 } 280 281 public static Chart<Artist> getMetroHypeArtistChart(Metro metro, String start, String end, String apiKey) { 282 return getMetroHypeArtistChart(metro.getCountry(), metro.getName(), start, end, apiKey); 283 } 284 285 public static Chart<Artist> getMetroHypeArtistChart(String country, String metro, String start, String end, String apiKey) { 286 return Chart.getChart("geo.getMetroHypeArtistChart", "artist", StringUtilities.map("country", country, "metro", metro), start, end, 287 -1, apiKey); 288 } 289 290 public static Chart<Track> getMetroHypeTrackChart(String country, String metro, String apiKey) { 291 return getMetroHypeTrackChart(country, metro, null, null, apiKey); 292 } 293 294 public static Chart<Track> getMetroHypeTrackChart(Metro metro, String start, String end, String apiKey) { 295 return getMetroHypeTrackChart(metro.getCountry(), metro.getName(), start, end, apiKey); 296 } 297 298 public static Chart<Track> getMetroHypeTrackChart(String country, String metro, String start, String end, String apiKey) { 299 return Chart.getChart("geo.getMetroHypeTrackChart", "track", StringUtilities.map("country", country, "metro", metro), start, end, 300 -1, apiKey); 301 } 302 303 public static Chart<Artist> getMetroUniqueArtistChart(String country, String metro, String apiKey) { 304 return getMetroUniqueArtistChart(country, metro, null, null, apiKey); 305 } 306 307 public static Chart<Artist> getMetroUniqueArtistChart(Metro metro, String start, String end, String apiKey) { 308 return getMetroUniqueArtistChart(metro.getCountry(), metro.getName(), start, end, apiKey); 309 } 310 311 public static Chart<Artist> getMetroUniqueArtistChart(String country, String metro, String start, String end, String apiKey) { 312 return Chart.getChart("geo.getMetroUniqueArtistChart", "artist", StringUtilities.map("country", country, "metro", metro), start, 313 end, -1, apiKey); 314 } 315 316 public static Chart<Track> getMetroUniqueTrackChart(String country, String metro, String apiKey) { 317 return getMetroUniqueTrackChart(country, metro, null, null, apiKey); 318 } 319 320 public static Chart<Track> getMetroUniqueTrackChart(Metro metro, String start, String end, String apiKey) { 321 return getMetroUniqueTrackChart(metro.getCountry(), metro.getName(), start, end, apiKey); 322 } 323 324 public static Chart<Track> getMetroUniqueTrackChart(String country, String metro, String start, String end, String apiKey) { 325 return Chart.getChart("geo.getMetroUniqueTrackChart", "track", StringUtilities.map("country", country, "metro", metro), start, end, 326 -1, apiKey); 327 } 328}