/*
* Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner,
* Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain,
* Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter,
* Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann,
* Samuel Zweifel
*
* This file is part of Jukefox.
*
* Jukefox is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or any later version. Jukefox is
* distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Jukefox. If not, see <http://www.gnu.org/licenses/>.
*/
package ch.ethz.dcg.jukefox.data.db;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import ch.ethz.dcg.jukefox.commons.DataUnavailableException;
import ch.ethz.dcg.jukefox.commons.DataWriteException;
import ch.ethz.dcg.jukefox.commons.utils.Pair;
import ch.ethz.dcg.jukefox.commons.utils.kdtree.KdTreePoint;
import ch.ethz.dcg.jukefox.data.cache.PreloadedSongInfo;
import ch.ethz.dcg.jukefox.data.context.AbstractContextResult;
import ch.ethz.dcg.jukefox.manager.libraryimport.AbstractAlbumCoverFetcherThread.AlbumFetcherResult;
import ch.ethz.dcg.jukefox.model.collection.AlbumStatus;
import ch.ethz.dcg.jukefox.model.collection.BaseAlbum;
import ch.ethz.dcg.jukefox.model.collection.BaseArtist;
import ch.ethz.dcg.jukefox.model.collection.BaseSong;
import ch.ethz.dcg.jukefox.model.collection.CompleteAlbum;
import ch.ethz.dcg.jukefox.model.collection.CompleteArtist;
import ch.ethz.dcg.jukefox.model.collection.CompleteTag;
import ch.ethz.dcg.jukefox.model.collection.Genre;
import ch.ethz.dcg.jukefox.model.collection.ListAlbum;
import ch.ethz.dcg.jukefox.model.collection.MapAlbum;
import ch.ethz.dcg.jukefox.model.collection.MapTag;
import ch.ethz.dcg.jukefox.model.collection.PlaylistSong;
import ch.ethz.dcg.jukefox.model.collection.SongCoords;
import ch.ethz.dcg.jukefox.model.collection.SongStatus;
import ch.ethz.dcg.jukefox.model.collection.statistics.CollectionProperties;
import ch.ethz.dcg.jukefox.model.libraryimport.GenreSongMap;
import ch.ethz.dcg.jukefox.model.libraryimport.ImportSong;
import ch.ethz.dcg.jukefox.model.libraryimport.WebDataSong;
import ch.ethz.dcg.jukefox.model.player.playlog.PlayLogSendEntity;
public interface IDbDataPortal {
public boolean isOpen();
public void close();
public String getSongPath(BaseSong<BaseArtist, BaseAlbum> song) throws DataUnavailableException;
public void insertSongGenreMapping(int genreId, int songId) throws DataWriteException;
public void deleteGenreSongMapping(int genreId, int songId) throws DataWriteException;
public GenreSongMap getGenreSongMappings() throws DataUnavailableException;
public int insertGenre(String name) throws DataWriteException;
/**
* Begins an immediate transaction. Transactions can be nested. When the outer transaction is ended all of the work
* done in that transaction and all of the nested transactions will be committed or rolled back. The changes will be
* rolled back if any transaction is ended without being marked as clean (by calling setTransactionSuccessful).
* Otherwise they will be committed.
*
* <p>
* Here is the standard idiom for transactions:
* </p>
*
* <pre>
* db.beginTransaction();
* try {
* ...
* db.setTransactionSuccessful();
* } finally {
* db.endTransaction();
* }
* </pre>
*/
public void beginTransaction();
/**
* Begins an exclusive transaction.
*
* @see #beginTransaction()
*/
public void beginExclusiveTransaction();
/**
* Returns true, if the current thread is in a transaction.
*
* @return If we are in a transaction
*/
public boolean inTransaction();
/**
* Marks the current transaction as successful. Do not do any more database work between calling this and calling
* endTransaction. Do as little non-database work as possible in that situation too. If any errors are encountered
* between this and endTransaction the transaction will still be committed.
*/
public void setTransactionSuccessful();
/**
* End a transaction. See {@link #beginTransaction()} for notes about how to use this and when transactions are
* committed and rolled back.
*/
public void endTransaction();
public void removeUnusedAlbums() throws DataWriteException;
public void removeSongById(int jukefoxId) throws DataWriteException;
public int insertSong(ImportSong s) throws DataWriteException;
public HashMap<String, ImportSong> getAllSongsForImport() throws DataUnavailableException;
public List<MapAlbum> getAllMapAlbums();
public CompleteAlbum getCompleteAlbumById(int albumId) throws DataUnavailableException;
public List<BaseSong<BaseArtist, BaseAlbum>> getSongListForAlbum(BaseAlbum album);
public String getAlbumArtPath(BaseAlbum album, boolean lowRes) throws DataUnavailableException;
public List<MapTag> getHighestVarianceTags(int numTags);
public int insertTag(int meId, String name, float[] coords) throws DataWriteException;
public int replaceFamousArtist(int meId, String name, String meName) throws DataWriteException;
public void batchInsertFamousArtists(int[] ids, String[] names, float[][] coords) throws DataWriteException;
public void insertArtistCoords(int artistId, float[] coords) throws DataWriteException;
public void emptyArtistsTable() throws DataWriteException;
public void emptyTagsTable() throws DataWriteException;
public void emptyArtistCoordsTable() throws DataWriteException;
public List<ListAlbum> getAllAlbumsAsListAlbums();
public void logArtistSetTable();
public List<ListAlbum> getAllAlbumsForArtist(BaseArtist artist, boolean includeCompilations);
public List<BaseArtist> getAllArtists();
public List<BaseSong<BaseArtist, BaseAlbum>> getAllSongs();
public BaseSong<BaseArtist, BaseAlbum> getBaseSongById(int randomId) throws DataUnavailableException;
public List<BaseSong<BaseArtist, BaseAlbum>> batchGetBaseSongByIds(Set<Integer> randomIds)
throws DataUnavailableException;
public Integer getTagId(String tagName, boolean onlyRelevantTags) throws DataUnavailableException;
public CompleteTag getCompleteTagById(int tagId) throws DataUnavailableException;
/**
* Should only be called by the PreloadedDataManager If you need tags get it from the preloaded data
*
* @return
*/
public HashMap<Integer, CompleteTag> getCompleteTags(boolean onlyRelevantTags) throws DataUnavailableException;
/**
* returns songs that have one of the status specified in statuses or the according album has one of the statuses
* specified in albumStatuses TODO exception????
*/
public List<WebDataSong> getWebDataSongsForStatus(SongStatus[] statuses, AlbumStatus[] albumStatuses);
public void updateWebDataSong(WebDataSong song) throws DataWriteException;
public List<PlaylistSong<BaseArtist, BaseAlbum>> getSongListForPaths(List<String> paths);
public PlaylistSong<BaseArtist, BaseAlbum> getSongForPath(String path) throws DataUnavailableException;
public PlaylistSong<BaseArtist, BaseAlbum> getSongForPath(String path, boolean caseSensitive)
throws DataUnavailableException;
public List<Genre> getAllGenres();
public List<BaseSong<BaseArtist, BaseAlbum>> getSongsForArtist(BaseArtist artist);
public List<BaseSong<BaseArtist, BaseAlbum>> getSongsForGenre(Genre genre);
public List<BaseAlbum> getAllAlbumsWithoutAlbumArt();
public List<SongCoords> getSongCoords(boolean includeSongWithoutCoords);
public void insertAlbumArtInfo(BaseAlbum album, String highResPath, String lowResPath, int color, AlbumStatus status)
throws DataWriteException;
public List<Integer> getSongIdsForAlbum(int albumId);
public CompleteArtist getCompleteArtist(BaseArtist baseArtist) throws DataUnavailableException;
public Integer getMusicExplorerArtistId(BaseArtist artist) throws DataUnavailableException;
public List<ListAlbum> findAlbumBySearchString(String searchTerm, int maxResults);
public List<BaseArtist> findArtistBySearchString(String searchTerm, int maxResults);
public List<BaseArtist> findFamousArtistBySearchString(String searchTerm, int maxResults);
public List<BaseSong<BaseArtist, BaseAlbum>> findTitleBySearchString(String searchTerm, int maxResults);
public CompleteAlbum getCompleteAlbum(BaseAlbum album) throws DataUnavailableException;
public List<PreloadedSongInfo> getPreloadedSongInfo();
public Integer getMusicExplorerIdForSong(BaseSong<BaseArtist, BaseAlbum> song) throws DataUnavailableException;
public void setRelevantTags(Collection<CompleteTag> relevantTags) throws DataWriteException;
public List<BaseSong<BaseArtist, BaseAlbum>> getSongListForIds(Vector<KdTreePoint<Integer>> points);
public List<Pair<BaseSong<BaseArtist, BaseAlbum>, KdTreePoint<Integer>>> getSongListForIds2(
Vector<KdTreePoint<Integer>> points);
public void updateSongsPcaCoords(HashMap<Integer, float[]> songPcaCoords) throws DataWriteException;
public void updateMapAlbumsPcaCoords(Collection<MapAlbum> mapAlbums) throws DataWriteException;
public float[] getCoordsForSongById(int songId) throws DataUnavailableException;
public List<ListAlbum> getAlbumsForGenre(Genre genre);
public List<BaseArtist> getArtistsForGenre(Genre genre);
/**
*
* @param meArtistId
* the <i>music explorer</i> artist ID.
* @return
*/
public boolean hasArtistCoords(int meArtistId);
public MapAlbum getMapAlbum(BaseAlbum album) throws DataUnavailableException;
public SongCoords getSongCoordsById(Integer songId) throws DataUnavailableException;
public List<SongCoords> getSongCoordsById(List<Integer> songIds) throws DataUnavailableException;
public void deleteTagTable() throws DataWriteException;
public void removeObsoleteGenres() throws DataWriteException;
public void updateUnusedArtists() throws DataWriteException;
public MapAlbum getMapAlbumBySong(BaseSong<? extends BaseArtist, ? extends BaseAlbum> song)
throws DataUnavailableException;
/**
* Generates a string for the last played song that can then be sent to the server.
*
* @param profileId
* @param playLogVersion
* @param coordinateVersion
* @param lastSentId
* @return
* @throws DataUnavailableException
*/
public PlayLogSendEntity getPlayLogString(int profileId, int playLogVersion, int coordinateVersion, long lastSentId)
throws DataUnavailableException;
public long writePlayLogEntry(int profileId, PlaylistSong<BaseArtist, BaseAlbum> song, long utcTime,
int timeZoneOffset, int dayOfWeek, int hourOfDay, boolean skip, int playMode,
AbstractContextResult contextData, int playbackPosition) throws DataWriteException;
/**
* Drops all the tables (except backup tables) and recreates them with the newest definitions.
*/
public void resetDatabase();
/**
* Deletes the entire database (factory reset). Backup tables don't survive this action.
*
* @return True, if sucessful
*/
public boolean deleteDatabase();
public List<MapTag> getMapTags();
public BaseSong<BaseArtist, BaseAlbum> getArbitrarySongInTimeRange(int profileId, long fromTimestamp,
long toTimestamp) throws DataUnavailableException;
public BaseSong<BaseArtist, BaseAlbum> getBaseSongByMusicExplorerId(int meId) throws DataUnavailableException;
/**
* TODO: for debugging only...
*/
public void printPlayLog(int profileId);
public BaseSong<BaseArtist, BaseAlbum> getSongCloseToTimeRange(int profileId, long fromTimestamp, long toTimestamp,
float toleranceRange, float toleranceGlobal) throws DataUnavailableException;
public List<PlaylistSong<BaseArtist, BaseAlbum>> getSongsForTimeRange(int profileId, long fromTimestamp,
long toTimestamp, int number);
public int getRandomSongId() throws DataUnavailableException;
public HashSet<String> getAllSongsPaths() throws DataUnavailableException;
public HashMap<String, Integer> getSongPathToIdMapping() throws DataUnavailableException;
public List<String> getSongPathsForAlbumName(String name);
public List<Pair<Genre, Integer>> getGenresForArtist(BaseArtist artist) throws DataUnavailableException;
public float[] getCoordsForAlbum(BaseAlbum album) throws DataUnavailableException;
public int insertOrGetPlayerModelId(String name) throws DataWriteException;
boolean isSongInRecentHistory(int playerModelId, BaseSong<BaseArtist, BaseAlbum> baseSong,
int equalSongAvoidanceNumber) throws DataUnavailableException;
boolean isArtistInRecentHistory(int playerModelId, BaseArtist baseArtist, int similarArtistAvoidanceNumber)
throws DataUnavailableException;
public int getMaximumValue(String tblName, String columnName) throws DataUnavailableException;
/**
* Reads the {@link CollectionProperties} from the database.
*
* @return The {@link CollectionProperties} instance
*/
public CollectionProperties getCollectionProperties();
/**
* Writes the {@link CollectionProperties} into the database. It only writes the properties which actually contain
* data.
*
* @param properties
* The {@link CollectionProperties}
* @throws DataWriteException
*/
public void setCollectionProperties(CollectionProperties properties) throws DataWriteException;
/**
* Returns the {@link IDbLogHelper} instance.
*
* @return The instance
*/
public IDbLogHelper getLogHelper();
/**
* Returns the {@link IDbStatisticsHelper} instance.
*
* @return The instance
*/
public IDbStatisticsHelper getStatisticsHelper();
/**
* Inserts the given song-genre mappings into the database.
*
* @param newMappings
* the mappings to be inserted.
*/
public void batchInsertSongGenreMappings(GenreSongMap newMappings);
/**
* Inserts the given songs into the database at once.
*
* @param songs
* The songs to be inserted.
*/
public void batchInsertSongs(Set<ImportSong> songs);
/**
* Updates the web data for all given songs.
*
* @param songs
* The songs whose web data should be updated.
*/
public void batchUpdateWebData(Set<WebDataSong> songs);
/**
* Updates the album cover information for all given albums.
*
* @param songs
* The songs whose web data should be updated.
*/
public void batchUpdateAlbumCovers(Set<AlbumFetcherResult> albumCovers);
/**
* Inserts all given tags to the database.
*
* @param tags
* The tags to be inserted into the database
*/
public void batchInsertTags(List<CompleteTag> tags);
// *** Key / Value *** //
/**
* Returns the key value pair in the given namespace. If the given key is not found, a
* {@link DataUnavailableException} is thrown.
*
* @param namespace
* The namespace
* @param key
* The key
* @return The value
* @throws DataUnavailableException
*/
public String getKeyValue(String namespace, String key) throws DataUnavailableException;
/**
* Returns the key value pair in the given namespace. If the given key is not found, a
* {@link DataUnavailableException} is thrown.
*
* @param namespace
* The namespace
* @param key
* The key
* @return The value
* @throws DataUnavailableException
*/
public int getKeyValueInt(String namespace, String key) throws DataUnavailableException;
/**
* Returns the key value pair in the given namespace. If the given key is not found, a
* {@link DataUnavailableException} is thrown.
*
* @param namespace
* The namespace
* @param key
* The key
* @return The value
* @throws DataUnavailableException
*/
public double getKeyValueDouble(String namespace, String key) throws DataUnavailableException;
/**
* Sets the key value pair in the given namespace.
*
* @param namespace
* The namespace
* @param key
* The key
* @param value
* The value
* @throws DataWriteException
*/
public void setKeyValue(String namespace, String key, String value) throws DataWriteException;
/**
* Sets the key value pair in the given namespace.
*
* @param namespace
* The namespace
* @param key
* The key
* @param value
* The value
* @throws DataWriteException
*/
public void setKeyValue(String namespace, String key, int value) throws DataWriteException;
/**
* Sets the key value pair in the given namespace.
*
* @param namespace
* The namespace
* @param key
* The key
* @param value
* The value
* @throws DataWriteException
*/
public void setKeyValue(String namespace, String key, double value) throws DataWriteException;
}