package com.pugh.sockso.web.action;
import com.pugh.sockso.cache.CacheException;
import com.pugh.sockso.cache.ObjectCache;
import com.pugh.sockso.Utils;
import com.pugh.sockso.db.Database;
import com.pugh.sockso.web.BadRequestException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import org.apache.log4j.Logger;
import com.google.inject.Inject;
public class AudioScrobbler {
private final int ONE_HOUR_IN_SECONDS = 60 * 60;
private final int CACHE_TIMEOUT_IN_SECONDS = ONE_HOUR_IN_SECONDS;
private final Logger log = Logger.getLogger( AudioScrobbler.class );
private Database db;
private ObjectCache cache;
/**
* Creates a new AudioScrobbler object
*
* @param db
*
*/
@Inject
public AudioScrobbler( final Database db, final ObjectCache cache ) {
this.db = db;
this.cache = cache;
}
/**
* Fetches related artist info
*
* @param artistId
*
* @return
*
* @throws IOException
* @throws SQLException
* @throws BadRequestException
*
*/
public String[] getSimilarArtists( final int artistId ) throws IOException, SQLException, BadRequestException, CacheException {
final String cacheKey = "web.action.AudioScrobbler.similar." +artistId;
if ( !cache.isCached(cacheKey) ) {
cache.write(
cacheKey,
getSimilarArtists( getArtistName(artistId) ),
CACHE_TIMEOUT_IN_SECONDS
);
}
return (String[]) cache.read( cacheKey );
}
/**
* Fetches similar artists by artist name
*
* @param artistName
*
* @return
*
* @throws IOException
*
*/
protected String[] getSimilarArtists( final String artistName ) throws IOException {
BufferedReader in = null;
try {
log.debug( "Fetching similar artists for: " +artistName );
final String url = "http://ws.audioscrobbler.com/1.0/artist/" +Utils.URLEncode(artistName)+ "/similar.txt";
final HttpURLConnection cnn = getHttpURLConnection( url );
final ArrayList<String> artists = new ArrayList<String>();
String s = "";
in = new BufferedReader(new InputStreamReader(cnn.getInputStream()) );
while ( (s = in.readLine()) != null ) {
final String[] info = s.split( "," );
artists.add( info[2] );
}
return artists.toArray( new String[] {} );
}
finally {
Utils.close( in );
}
}
/**
* Resolves an artist id to name, or throws an exception
*
* @param artistId
*
* @return
*
* @throws SQLException
* @throws BadRequestException
*
*/
protected String getArtistName( final int artistId ) throws SQLException, BadRequestException {
ResultSet rs = null;
PreparedStatement st = null;
try {
final String sql = " select name " +
" from artists " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, artistId );
rs = st.executeQuery();
if ( !rs.next() )
throw new BadRequestException( "unknown artist", 404 );
return rs.getString( "name" );
}
finally {
Utils.close( rs );
Utils.close( st );
}
}
/**
* Returns a connection object for the specified URL (seam for testing)
*
* @param url
*
* @return
*
* @throws IOException
*
*/
protected HttpURLConnection getHttpURLConnection( final String url ) throws IOException {
return (HttpURLConnection) new URL( url ).openConnection();
}
}