package com.pugh.sockso.music;
import com.pugh.sockso.Constants;
import com.pugh.sockso.Properties;
import com.pugh.sockso.Utils;
import com.pugh.sockso.db.Database;
import com.pugh.sockso.music.indexing.CoverArtIndexer;
import com.pugh.sockso.music.indexing.IndexEvent;
import com.pugh.sockso.music.indexing.IndexListener;
import com.pugh.sockso.music.indexing.Indexer;
import com.pugh.sockso.music.tag.AudioTag;
import com.pugh.sockso.music.tag.InvalidTagException;
import com.pugh.sockso.music.tag.Tag;
import com.pugh.sockso.web.User;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.log4j.Logger;
import org.apache.commons.lang3.StringUtils;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class DBCollectionManager extends Thread implements CollectionManager, IndexListener {
private static final Logger log = Logger.getLogger( DBCollectionManager.class );
private final Database db;
private final Properties p;
private final List<CollectionManagerListener> listeners;
private final Indexer indexer;
/**
* constructor
*
*/
@Inject
public DBCollectionManager( final Database db, final Properties p, final Indexer indexer ) {
this.db = db;
this.p = p;
this.indexer = indexer;
listeners = new ArrayList<CollectionManagerListener>();
}
/**
* The indexer has detected a change in the tracks we're indexing
*
* @param evt
*
*/
public void indexChanged( final IndexEvent evt ) {
try {
switch ( evt.getType() ) {
case UNKNOWN:
addFile( evt.getFileId(), evt.getFile() );
break;
case CHANGED:
checkTrack( getTrack(evt.getFileId()), evt.getFile() );
break;
case MISSING:
removeTrack( evt.getFileId() );
break;
case COMPLETE:
removeOrphans();
fireCollectionManagerEvent( CollectionManagerListener.UPDATE_COMPLETE, "Collection Updated!" );
break;
}
}
catch ( final Throwable t ) {
log.debug( "indexChanged error on file '" + evt.getFile().getAbsolutePath() + "'", t );
}
}
/**
* Extracts a track by ID
*
* @param trackId
*
* @return
*
* @throws java.sql.SQLException
*
*/
protected Track getTrack( final int trackId ) throws SQLException {
PreparedStatement st = null;
ResultSet rs = null;
try {
final String sql = Track.getSelectFromSql() +
" where t.id = ? ";
st = db.prepare( sql );
st.setInt( 1, trackId );
rs = st.executeQuery();
if ( !rs.next() ) {
throw new SQLException( "Invalid track id" );
}
return Track.createFromResultSet( rs );
}
finally {
Utils.close( rs );
Utils.close( st );
}
}
/**
* Tries to add an audio file to the collection, creating artist/album info
* if required.
*
* @param collectionId
* @param file
*
* @throws com.pugh.sockso.music.tag.InvalidTagException
* @throws java.io.IOException
*
*/
protected void addFile( final int collectionId, final File file ) throws InvalidTagException, IOException {
final Tag tag = AudioTag.getTag( file );
log.debug( tag.toString() );
final int artistId = addArtist( tag.getArtist() );
int albumArtistId = artistId;
if ( StringUtils.isBlank(tag.getAlbumArtist()) ) {
albumArtistId = addArtist( tag.getAlbumArtist() );
}
final int albumId = addAlbum( albumArtistId, tag.getAlbum(), tag.getAlbumYear() );
final int genreId = addGenre( tag.getGenre() );
final int trackId = addTrack( artistId, albumId, tag.getTrack(),
tag.getTrackNumber(), file, collectionId, genreId );
if ( Utils.isFeatureEnabled( p, Constants.COLLMAN_SCAN_COVERS ) ) {
final BufferedImage coverArt = tag.getCoverArt();
if ( coverArt != null ) {
addCoverArt( albumArtistId, "ar", coverArt );
addCoverArt( albumId, "al", coverArt );
addCoverArt( trackId, "tr", coverArt );
}
}
}
/**
* Adds cover art extracted from the tag for this track
*
* @param itemId
* @param itemType
* @param coverArt
*
*/
protected void addCoverArt( final int itemId, final String itemType, final BufferedImage coverArt ){
log.debug("Adding Cover Art for itemId: " + itemId + ", itemType: " + itemType);
// -1 if nothing inserted into db
if (itemId < 0) {
log.warn("addCoverArt: itemId param was -1");
return;
}
// TODO Would be nice if we had some sort of helper to build a coverId from arbitrary music item types
String coverId = itemType + itemId;
final CoverArtIndexer coverArtIndexer = new CoverArtIndexer(p);
coverArtIndexer.indexCover(new CoverArt( coverId, coverArt ));
}
/**
* Scans a folder for new files
*
* @param collectionId
* @param directory
*
*/
public void scanDirectory( final int collectionId, final File directory ) {
try {
indexer.scanDirectory( collectionId, directory );
}
catch ( final Exception e ) {
log.error( e );
}
}
/**
* checks the collection for updates. it actually does 2 scans, one
* to check for new files, and the second to check the files in the
* collection are still there.
*
*/
public void checkCollection() {
indexer.scan();
}
/**
* Re-reads tag information from files
*/
public void rescanTags() {
indexer.scan(Indexer.ScanFilter.NONE, Indexer.ScanScope.ALL_FILES);
}
/**
* checks if the album tag information has changed, if it has then updates
* the database.
*
* @param artistId
* @param tag
* @param track
*
* @throws java.sql.SQLException
*
*/
protected void checkAlbumTagInfo( final int artistId, final Tag tag, final Track track ) throws SQLException {
// need to ignore case because that's how the DB does it
if ( !track.getAlbum().getName().equalsIgnoreCase(tag.getAlbum()) ||
!track.getAlbum().getYear().equalsIgnoreCase(tag.getAlbumYear()) ) {
ResultSet rs = null;
PreparedStatement st = null;
try {
// if the album has changed, first try and fetch an album
// for this artist of this new name to tag track to...
String sql = " select id " +
" from albums " +
" where name = ? " +
" and artist_id = ? ";
st = db.prepare( sql );
st.setString( 1, tag.getAlbum() );
st.setInt( 2, artistId );
rs = st.executeQuery();
final int newAlbumId = rs.next()
? rs.getInt( "id" )
: addAlbum( artistId, tag.getAlbum(), tag.getAlbumYear() );
Utils.close( rs );
Utils.close( st );
// then update track
sql = " update tracks " +
" set album_id = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, newAlbumId );
st.setInt( 2, track.getId() );
st.execute();
Utils.close( rs );
Utils.close( st );
sql = " update albums " +
" set year = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setString( 1, tag.getAlbumYear() );
st.setInt( 2, newAlbumId );
st.execute();
}
finally {
Utils.close( rs );
Utils.close( st );
}
}
}
/**
* Checks if the artist information has changed.
* If it has changed, then the database is updated and the new artist id is
* returned.
* Otherwise, the artist id that's returned will be the one from the track
* that hasn't changed.
*
* @param tag
* @param track
*
* @return
*
* @throws java.sql.SQLException
*
*/
protected int checkArtistTagInfo( final Tag tag, final Track track ) throws SQLException {
// need to ignore case because that's how the DB does it
if ( !track.getArtist().getName().equalsIgnoreCase(tag.getArtist()) ) {
PreparedStatement st = null;
ResultSet rs = null;
try {
// if the artist has changed, first try and fetch an artist
// of this new name to tag track to...
String sql = " select id " +
" from artists " +
" where name = ? ";
st = db.prepare( sql );
st.setString( 1, tag.getArtist() );
rs = st.executeQuery();
final int newArtistId = rs.next()
? rs.getInt("id")
: addArtist(tag.getArtist());
Utils.close( rs );
Utils.close( st );
// then update track
sql = " update tracks " +
" set artist_id = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, newArtistId );
st.setInt( 2, track.getId() );
st.execute();
Utils.close( rs );
Utils.close( st );
sql = " update albums " +
" set artist_id = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, newArtistId );
st.setInt( 2, track.getAlbum().getId() );
st.execute();
return newArtistId;
}
finally {
Utils.close( rs );
Utils.close( st );
}
}
// name not changed, but make sure browse_name is up to date
// @TODO - maybe it'd be better to extract the browse_name with the artist
// information (in Track), then we can check if it needs changing...
// is this more unneeded overhead though?
else {
updateArtistBrowseName( track.getArtist().getId(), tag.getArtist() );
}
return track.getArtist().getId();
}
/**
* Updates the artists browse name from the real name
*
* @param artistId
* @param realName
*
* @throws java.sql.SQLException
*
*/
protected void updateArtistBrowseName( final int artistId, final String realName ) throws SQLException {
PreparedStatement st = null;
try {
final String browseName = getArtistBrowseName( getArtistPrefixesToRemove(), realName );
final String sql = " update artists " +
" set browse_name = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setString( 1, browseName );
st.setInt( 2, artistId );
st.execute();
}
finally {
Utils.close( st );
}
}
/**
* checks if a tracks tag has changed, and updates the database with the
* new information if it has.
*
* @param tag
* @param track
*
* @throws java.sql.SQLException
*
*/
protected void checkTrackTagInfo( final Tag tag, final Track track ) throws SQLException {
if ( !track.getName().equals(tag.getTrack()) || (track.getNumber() != tag.getTrackNumber()) ) {
PreparedStatement st = null;
try {
final String sql = " update tracks " +
" set name = ?, " +
" track_no = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setString( 1, tag.getTrack() );
st.setInt( 2, tag.getTrackNumber() );
st.setInt( 3, track.getId() );
st.execute();
}
finally {
Utils.close( st );
}
}
}
/**
* checks the genre's tag has changed and updates the database with the
* new information if it has.
*
* @param tag
* @param track
*
* @throws java.sql.SQLException
*
*/
private void checkGenreTagInfo( final Tag tag, final Track track ) throws SQLException {
final String genre = ( track.getGenre() == null ? null : track.getGenre().getName() );
if ( !tag.getGenre().equalsIgnoreCase(genre) ) {
PreparedStatement st = null;
ResultSet rs = null;
try {
// if the genre has changed, first try and fetch the genre
// of this new name to tag track to...
String sql = " select id " +
" from genres " +
" where name = ? ";
st = db.prepare( sql );
st.setString( 1, tag.getGenre() );
rs = st.executeQuery();
final int newGenreId = rs.next()
? rs.getInt("id")
: addGenre(tag.getGenre());
Utils.close( rs );
Utils.close( st );
// then update the track with the new genre
sql = " update tracks " +
" set genre_id = ? " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, newGenreId );
st.setInt( 2, track.getId() );
st.execute();
}
finally {
Utils.close( rs );
Utils.close( st );
}
}
}
/**
* checks that a track is up to date with the tag information of it's
* file on disk (it may have been edited between updates to the collection)
*
* @param track the track to check
* @param file the audio file on disk
*
*/
private void checkTrack( final Track track, final File file ) {
try {
final Tag tag = AudioTag.getTag( file );
// has track info changed?
checkTrackTagInfo( tag, track );
// has the artist information changed? if it has we'll get a new
// artist id, otherwise we'll get the same one as the track is
// assigned to when we passed in
final int artistId = checkArtistTagInfo( tag, track );
// has album info changed?
checkAlbumTagInfo( artistId, tag, track );
// has the genre info changed?
checkGenreTagInfo( tag, track );
}
catch ( SQLException e ) { log.debug(e); }
catch ( InvalidTagException e ) { log.debug(e); }
catch ( IOException e ) { log.debug(e); }
}
/**
* Given an artists name, removes any prefixes we've been asked to.
*
* @param prefixes
* @param name
*
* @return
*
*/
protected String getArtistBrowseName( final String[] prefixes, final String name ) {
for ( final String prefix : prefixes ) {
if ( name.substring(0,prefix.length()).equalsIgnoreCase(prefix) ) {
return name.substring( prefix.length() );
}
}
return name;
}
/**
* Returns an array of the artist prefixes we need to remove
*
* @return
*
*/
protected String[] getArtistPrefixesToRemove() {
return p.get( Constants.COLLMAN_ARTIST_REMOVE_PREFIXES ).split( "," );
}
/**
* removes a track from the collection
*
* @param s statement object to use
* @param trackId the track id to remove
*
*/
protected void removeTrack( final int trackId ) throws SQLException {
String sql = " delete from play_log " +
" where track_id = '" +trackId+ "' ";
db.update( sql );
sql = " delete from playlist_tracks " +
" where track_id = '" +trackId+ "' ";
db.update( sql );
sql = " delete from tracks " +
" where id = '" +trackId+ "' ";
db.update( sql );
}
/**
* allows components to register for collection activity messages
*
* @param listener the listener to register
*
*/
public void addCollectionManagerListener( final CollectionManagerListener listener ) {
listeners.add( listener );
}
/**
* signals all listeners that a collection manager event
* has just occurred
*
* @param type the event type
* @param message the event description
*
*/
public void fireCollectionManagerEvent( final int type, final String message ) {
for ( final CollectionManagerListener listener : listeners ) {
listener.collectionManagerChangePerformed( type, message );
}
}
/**
* adds a directory to the database and returns it's new collectionId
*
* @param dir
*
* @return
*
* @throws java.sql.SQLException
* @throws java.sql.SQLException
*
*/
protected int addDirectoryToDb( final File dir ) throws SQLException, SQLException {
ResultSet rs = null;
PreparedStatement st = null;
try {
// add to the database
String sql = " insert into collection ( path ) " +
" values ( ? ) ";
st = db.prepare( sql );
st.setString( 1, Utils.getPathWithSlash(dir) );
st.execute();
Utils.close( st );
// extract new id
sql = " select max(c.id) as new_id " +
" from collection c ";
st = db.prepare( sql );
rs = st.executeQuery();
if (!rs.next())
throw new SQLException("unable to retrieve new id");
return rs.getInt("new_id");
}
finally {
Utils.close( rs );
Utils.close( st );
}
}
/**
* adds a directory to the collection
*
* @param dir the directory to add
*
*/
public int addDirectory( final File dir ) {
try {
// add to database
int collectionId = addDirectoryToDb( dir );
indexer.scanDirectory( collectionId, dir );
removeOrphans();
fireCollectionManagerEvent( CollectionManagerListener.UPDATE_COMPLETE, "Update Finished" );
return collectionId;
}
catch ( final Exception e ) {
log.error( "Error adding folder to collection: " + e.getMessage() );
fireCollectionManagerEvent( CollectionManagerListener.ERROR, e.getMessage() );
}
return -1;
}
/**
* adds an artist to the collection (if it doesn't already
* exist) and returns its id
*
*/
private int addArtist( String name ) {
if ( StringUtils.isBlank(name) ) {
name = "Unknown Artist";
}
ResultSet rs = null;
PreparedStatement st = null;
try {
try {
final String browseName = getArtistBrowseName( getArtistPrefixesToRemove(), name );
st = db.prepare(
" insert into artists ( name, date_added, browse_name ) " +
" values ( ?, current_timestamp, ? ) "
);
st.setString( 1, name );
st.setString( 2, browseName );
st.execute();
log.debug( "Added Artist: " + name );
}
catch ( final Exception e ) {}
finally {
Utils.close( st );
}
st = db.prepare(
" select id " +
" from artists " +
" where name = ? "
);
st.setString( 1, name );
rs = st.executeQuery();
if ( rs.next() ) {
fireCollectionManagerEvent( CollectionManagerListener.ARTIST_ADDED, name );
return rs.getInt( "id" );
}
}
catch ( final Exception e ) {
log.error( "Error Adding Artist: " + e );
}
finally {
Utils.close( rs );
Utils.close( st );
System.gc();
}
return -1;
}
/**
* adds an album to the collection (if it doesn't already
* exist) and returns its id
*
*/
private int addAlbum( final int artistId, String name, String year ) {
if ( StringUtils.isBlank(name) ) {
name = "Unknown Album";
}
ResultSet rs = null;
PreparedStatement st = null;
try {
try {
st = db.prepare(
" insert into albums ( artist_id, name, year, date_added ) " +
" values ( ?, ?, ?, current_timestamp ) "
);
st.setInt( 1, artistId );
st.setString( 2, name );
st.setString(3, year);
st.execute();
log.debug( "Added Album: " + name + " " + year );
}
catch ( final Exception e ) {}
finally {
Utils.close( st );
}
final String sql = " select id " +
" from albums " +
" where artist_id = ? " +
" and name = ? ";
st = db.prepare( sql );
st.setInt( 1, artistId );
st.setString( 2, name );
rs = st.executeQuery();
if ( rs.next() ) {
fireCollectionManagerEvent( CollectionManagerListener.ALBUM_ADDED, name );
return rs.getInt( "id" );
}
}
catch ( final Exception e ) {
log.error( "Error Adding Album (" + name + "): " + e.getMessage() );
}
finally {
Utils.close( rs );
Utils.close( st );
}
return -1;
}
/**
* adds a genre to the collection (if it doesn't already
* exist) and returns its id
*
*/
private int addGenre( String name ) {
if ( StringUtils.isBlank(name) ) {
name = "Unknown Genre";
}
ResultSet rs = null;
PreparedStatement st = null;
try {
try {
st = db.prepare(
" insert into genres ( name ) " +
" values ( ? ) "
);
st.setString( 1, name );
st.execute();
log.debug( "Added Genre: " + name );
}
catch (Exception e) {}
finally {
Utils.close( st );
}
st = db.prepare(
" select id " +
" from genres " +
" where name = ? "
);
st.setString( 1, name );
rs = st.executeQuery();
if ( rs.next() ) {
fireCollectionManagerEvent( CollectionManagerListener.GENRE_ADDED, name );
return rs.getInt( "id" );
}
}
catch ( final Exception e ) {
log.error( "Error Adding Genre: " + e );
}
finally {
Utils.close( rs );
Utils.close( st );
}
return -1;
}
/**
* adds a track to the collection (if it doesn't already
* exist) and returns its id
*
*/
private int addTrack( final int artistId, final int albumId, String name,
final int trackNo, final File file, final int collectionId, final int genreId ) {
if ( StringUtils.isBlank(name) ) {
name = "Unknown Track (" + trackNo + ")";
}
ResultSet rs = null;
PreparedStatement st = null;
try {
try {
final String sql = " insert into tracks ( artist_id, album_id, name, path, " +
" length, collection_id, date_added, track_no, genre_id ) " +
" values ( ?, ?, ?, ?, 100, ?, current_timestamp, ?, ? ) ";
st = db.prepare( sql );
st.setInt( 1, artistId );
st.setInt( 2, albumId );
st.setString( 3, name );
st.setString( 4, file.getAbsolutePath() );
st.setInt( 5, collectionId );
st.setInt( 6, trackNo );
st.setInt( 7, genreId);
st.execute();
log.debug( "Added Track: " + name );
}
catch ( final Exception e ) {}
finally {
Utils.close( st );
}
final String sql = " select id " +
" from tracks " +
" where artist_id = ? " +
" and album_id = ? " +
" and name = ? ";
st = db.prepare( sql );
st.setInt( 1, artistId );
st.setInt( 2, albumId );
st.setString( 3, name );
rs = st.executeQuery();
if ( rs.next() ) {
fireCollectionManagerEvent( CollectionManagerListener.TRACK_ADDED, name );
return rs.getInt( "id" );
}
}
catch ( final Exception e ) {
log.error( "Error Adding Track: " + e.getMessage() );
}
finally {
Utils.close( rs );
Utils.close( st );
}
return -1;
}
/**
* removes a directory from the collection
*
* @param path the path of the directory to remove
*
*/
public boolean removeDirectory( final String path ) {
ResultSet rs = null;
PreparedStatement st = null;
try {
// first we need to get the collection id
String sql = " select id " +
" from collection c " +
" where path = ? ";
st = db.prepare( sql );
st.setString( 1, Utils.getPathWithSlash(path) );
rs = st.executeQuery();
if ( rs.next() ) {
final int collectionId = rs.getInt( "id" );
Utils.close( rs );
Utils.close( st );
// remove items from the play_log
sql = " delete from play_log " +
" where track_id in ( " +
" select id " +
" from tracks t " +
" where collection_id = ? " +
" ) ";
st = db.prepare( sql );
st.setInt( 1, collectionId );
st.execute();
Utils.close( st );
// remove tracks from playlists
sql = " delete from playlist_tracks " +
" where track_id in ( select id " +
" from tracks " +
" where collection_id = ? ) ";
st = db.prepare( sql );
st.setInt( 1, collectionId );
st.execute();
Utils.close( st );
// remove tracks from the collection
sql = " delete from tracks " +
" where collection_id = ? ";
st = db.prepare( sql );
st.setInt( 1, collectionId );
st.execute();
Utils.close( st );
// remove the collection
sql = " delete from collection " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, collectionId );
st.execute();
Utils.close( st );
removeOrphans();
fireCollectionManagerEvent( CollectionManagerListener.UPDATE_COMPLETE, "Directory Removed" );
return true;
}
}
catch ( final SQLException e ) {
log.error( e.getMessage() );
}
finally {
Utils.close( rs );
Utils.close( st );
}
return false;
}
/**
* Clean up unreferenced artists, albums, genres from database
*
* @throws SQLException
*/
protected void removeOrphans() throws SQLException {
removeOrphanedArtists();
removeOrphanedAlbums();
removeOrphanedGenres();
}
/**
* Removes any artists from the collection that don't
* have any tracks associated with them
*
* @throws SQLException
*
*/
protected void removeOrphanedArtists() throws SQLException {
// remove any artists left without tracks OR albums
// (artist can be an "album artist" and have zero tracks)
String sql = " delete from artists " +
" where id not in ( select artist_id from albums ) " +
" and id not in ( select artist_id from tracks ) ";
db.update( sql );
}
/**
* Removes any albums from the collection that don't
* have any tracks associated with them
*
* @throws SQLException
*
*/
protected void removeOrphanedAlbums() throws SQLException {
// remove any albums left without tracks
String sql = " delete from albums " +
" where id not in ( select album_id " +
" from tracks ) ";
db.update( sql );
}
/**
* removes any albums from the collection that don't
* have any tracks associated with them
*
* @throws SQLException
*
*/
protected void removeOrphanedGenres() throws SQLException {
// remove any genres left without tracks
String sql = " delete from genres " +
" where id not in ( select genre_id " +
" from tracks ) ";
db.update( sql );
}
public int savePlaylist( final String name, final Track[] tracks ) {
return savePlaylist( name, tracks, null );
}
/**
* saves a playlist for a user to the collection
*
* @param name the name of the playlist
* @param tracks track ids for the playlist
*
*/
public int savePlaylist( final String name, final Track[] tracks, final User user ) {
ResultSet rs = null;
PreparedStatement st = null;
try {
int playlistId = -1;
// see if old playlist exists
String sql = " select id " +
" from playlists p " +
" where name = ? ";
st = db.prepare( sql );
st.setString( 1, name );
rs = st.executeQuery();
if ( rs.next() )
removePlaylist( rs.getInt("id") );
Utils.close( rs );
Utils.close( st );
// create playlist
sql = " insert into playlists ( name, user_id, date_created, date_modified ) " +
" values ( ?, ?, current_timestamp, current_timestamp ) ";
st = db.prepare( sql );
st.setString( 1, name );
if ( user == null )
st.setNull( 2, Types.INTEGER );
else
st.setInt( 2, user.getId() );
st.execute();
Utils.close( rs );
Utils.close( st );
// fetch new id
sql = " select max(p.id) as new_id " +
" from playlists p ";
st = db.prepare( sql );
rs = st.executeQuery();
if ( rs.next() )
playlistId = rs.getInt( "new_id" );
else
throw new SQLException( "couldn't get new playlist id" );
Utils.close( rs );
Utils.close( st );
// then add tracks to playlist
sql = " insert into playlist_tracks ( playlist_id, track_id ) " +
" values ( ?, ? ) ";
st = db.prepare( sql );
for ( final Track track : tracks ) {
st.setInt( 1, playlistId );
st.setInt( 2, track.getId() );
st.execute();
}
fireCollectionManagerEvent( CollectionManagerListener.PLAYLISTS_CHANGED, name );
return playlistId;
}
catch ( final SQLException e ) {
log.error( e.getMessage() );
}
finally {
Utils.close( rs );
Utils.close( st );
}
return -1;
}
/**
* tries to remove a playlist from the collection, returns a boolean
* indicating if it was successful
*
* @param id id of playlist to remove
* @return boolean indicating success
*
*/
public boolean removePlaylist( final int id ) {
PreparedStatement st = null;
try {
String sql = " delete from playlist_tracks " +
" where playlist_id = ? ";
st = db.prepare( sql );
st.setInt( 1, id );
st.execute();
Utils.close( st );
sql = " delete from playlists " +
" where id = ? ";
st = db.prepare( sql );
st.setInt( 1, id );
st.execute();
fireCollectionManagerEvent( CollectionManagerListener.PLAYLISTS_CHANGED, "Playlist removed" );
}
catch ( final SQLException e ) {
log.error( e );
return false;
}
finally {
Utils.close( st );
}
return true;
}
}