Commit 319a454e authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Add handling for Movie

parent 8ab98952
......@@ -34,6 +34,8 @@ class IFile
virtual const std::string& mrl() const = 0;
virtual bool addLabel( LabelPtr label ) = 0;
virtual bool removeLabel( LabelPtr label ) = 0;
virtual MoviePtr movie() = 0;
virtual bool setMovie( MoviePtr movie ) = 0;
virtual std::vector<std::shared_ptr<ILabel> > labels() = 0;
};
......
......@@ -10,6 +10,7 @@ class IAlbumTrack;
class IFile;
class ILabel;
class IMetadataService;
class IMovie;
class IShow;
class IShowEpisode;
......@@ -19,6 +20,7 @@ typedef std::shared_ptr<IAlbum> AlbumPtr;
typedef std::shared_ptr<IAlbumTrack> AlbumTrackPtr;
typedef std::shared_ptr<IShow> ShowPtr;
typedef std::shared_ptr<IShowEpisode> ShowEpisodePtr;
typedef std::shared_ptr<IMovie> MoviePtr;
class IMediaLibrary
{
......@@ -37,6 +39,8 @@ class IMediaLibrary
virtual AlbumPtr createAlbum( const std::string& id3Tag ) = 0;
virtual ShowPtr show( const std::string& name ) = 0;
virtual ShowPtr createShow( const std::string& name ) = 0;
virtual MoviePtr movie( const std::string& title ) = 0;
virtual MoviePtr createMovie( const std::string& title ) = 0;
virtual void addMetadataService( IMetadataService* service ) = 0;
};
......
#ifndef IMOVIE_H
#define IMOVIE_H
#include "IMediaLibrary.h"
class IMovie
{
public:
virtual ~IMovie() {}
virtual unsigned int id() const = 0;
virtual const std::string& title() const = 0;
virtual time_t releaseDate() const = 0;
virtual bool setReleaseDate( time_t date ) = 0;
virtual const std::string& shortSummary() const = 0;
virtual bool setShortSummary( const std::string& summary ) = 0;
virtual const std::string& artworkUrl() const = 0;
virtual bool setArtworkUrl( const std::string& artworkUrl ) = 0;
virtual const std::string& imdbId() const = 0;
virtual bool setImdbId( const std::string& id ) = 0;
virtual bool destroy() = 0;
virtual bool files( std::vector<FilePtr>& files ) = 0;
};
#endif // IMOVIE_H
......@@ -29,6 +29,7 @@ list(APPEND SRC_LIST ${HEADERS_LIST}
AlbumTrack.cpp
ShowEpisode.cpp
Factory.cpp
Movie.cpp
)
find_package(Sqlite3 REQUIRED)
......
......@@ -6,6 +6,7 @@
#include "AlbumTrack.h"
#include "File.h"
#include "Label.h"
#include "Movie.h"
#include "ShowEpisode.h"
#include "SqliteTools.h"
......@@ -23,6 +24,7 @@ File::File( sqlite3* dbConnection, sqlite3_stmt* stmt )
m_playCount = sqlite3_column_int( stmt, 4 );
m_showEpisodeId = sqlite3_column_int( stmt, 5 );
m_mrl = (const char*)sqlite3_column_text( stmt, 6 );
m_movieId = Traits<unsigned int>::Load( stmt, 7 );
}
File::File( const std::string& mrl )
......@@ -34,6 +36,7 @@ File::File( const std::string& mrl )
, m_playCount( 0 )
, m_showEpisodeId( 0 )
, m_mrl( mrl )
, m_movieId( 0 )
{
}
......@@ -114,6 +117,26 @@ const std::string& File::mrl() const
return m_mrl;
}
MoviePtr File::movie()
{
if ( m_movie == nullptr && m_movieId != 0 )
{
m_movie = Movie::fetch( m_dbConnection, m_movieId );
}
return m_movie;
}
bool File::setMovie( MoviePtr movie )
{
static const std::string req = "UPDATE " + policy::FileTable::Name
+ " SET movie_id = ? WHERE id_file = ?";
if ( SqliteTools::executeUpdate( m_dbConnection, req, movie->id(), m_id ) == false )
return false;
m_movie = movie;
m_movieId = movie->id();
return true;
}
unsigned int File::id() const
{
return m_id;
......@@ -129,10 +152,13 @@ bool File::createTable(sqlite3* connection)
"play_count UNSIGNED INTEGER,"
"show_episode_id UNSIGNED INTEGER,"
"mrl TEXT UNIQUE ON CONFLICT FAIL,"
"movie_id UNSIGNED INTEGER,"
"FOREIGN KEY (album_track_id) REFERENCES " + policy::AlbumTrackTable::Name
+ "(id_track) ON DELETE CASCADE,"
"FOREIGN KEY (show_episode_id) REFERENCES " + policy::ShowEpisodeTable::Name
+ "(id_episode) ON DELETE CASCADE"
+ "(id_episode) ON DELETE CASCADE,"
"FOREIGN KEY (movie_id) REFERENCES " + policy::MovieTable::Name
+ "(id_movie) ON DELETE CASCADE"
")";
return SqliteTools::executeRequest( connection, req );
}
......
......@@ -56,6 +56,8 @@ class File : public IFile, public Cache<File, IFile, policy::FileTable, policy::
virtual std::vector<std::shared_ptr<ILabel> > labels();
virtual int playCount() const;
virtual const std::string& mrl() const;
virtual MoviePtr movie();
virtual bool setMovie( MoviePtr movie );
private:
sqlite3* m_dbConnection;
......@@ -68,11 +70,13 @@ class File : public IFile, public Cache<File, IFile, policy::FileTable, policy::
unsigned int m_playCount;
unsigned int m_showEpisodeId;
std::string m_mrl;
unsigned int m_movieId;
// Auto fetched related properties
Album* m_album;
AlbumTrackPtr m_albumTrack;
ShowEpisodePtr m_showEpisode;
MoviePtr m_movie;
friend class Cache<File, IFile, policy::FileTable, policy::FileCache>;
friend struct policy::FileTable;
......
......@@ -8,6 +8,7 @@
#include "Label.h"
#include "Album.h"
#include "AlbumTrack.h"
#include "Movie.h"
#include "Show.h"
#include "ShowEpisode.h"
......@@ -24,6 +25,7 @@ MediaLibrary::~MediaLibrary()
AlbumTrack::clear();
Show::clear();
ShowEpisode::clear();
Movie::clear();
}
bool MediaLibrary::initialize(const std::string& dbPath)
......@@ -38,7 +40,8 @@ bool MediaLibrary::initialize(const std::string& dbPath)
Album::createTable( m_dbConnection ) &&
AlbumTrack::createTable( m_dbConnection ) &&
Show::createTable( m_dbConnection ) &&
ShowEpisode::createTable( m_dbConnection ) );
ShowEpisode::createTable( m_dbConnection ) &&
Movie::createTable( m_dbConnection ) );
}
......@@ -107,6 +110,18 @@ ShowPtr MediaLibrary::createShow(const std::string& name)
return Show::create( m_dbConnection, name );
}
MoviePtr MediaLibrary::movie( const std::string& title )
{
static const std::string req = "SELECT * FROM " + policy::MovieTable::Name
+ " WHERE title = ?";
return SqliteTools::fetchOne<Movie>( m_dbConnection, req, title );
}
MoviePtr MediaLibrary::createMovie( const std::string& title )
{
return Movie::create( m_dbConnection, title );
}
void MediaLibrary::addMetadataService(IMetadataService* service)
{
typedef std::unique_ptr<IMetadataService> MdsPtr;
......
......@@ -28,6 +28,9 @@ class MediaLibrary : public IMediaLibrary
virtual ShowPtr show( const std::string& name );
virtual ShowPtr createShow( const std::string& name );
virtual MoviePtr movie( const std::string& title );
virtual MoviePtr createMovie( const std::string& title );
virtual void addMetadataService( IMetadataService* service );
private:
sqlite3* m_dbConnection;
......
#include "Movie.h"
#include "File.h"
#include "SqliteTools.h"
const std::string policy::MovieTable::Name = "Movie";
const std::string policy::MovieTable::CacheColumn = "id_movie";
unsigned int Movie::* const policy::MovieTable::PrimaryKey = &Movie::m_id;
Movie::Movie( sqlite3* dbConnection, sqlite3_stmt* stmt )
: m_dbConnection( dbConnection )
{
m_id = Traits<unsigned int>::Load( stmt, 0 );
m_title = Traits<std::string>::Load( stmt, 1 );
m_releaseDate = Traits<time_t>::Load( stmt, 2 );
m_summary = Traits<std::string>::Load( stmt, 3 );
m_artworkUrl = Traits<std::string>::Load( stmt, 4 );
m_imdbId = Traits<std::string>::Load( stmt, 5 );
}
Movie::Movie( const std::string& title )
: m_dbConnection( nullptr )
, m_id( 0 )
, m_title( title )
, m_releaseDate( 0 )
{
}
unsigned int Movie::id() const
{
return m_id;
}
const std::string&Movie::title() const
{
return m_title;
}
time_t Movie::releaseDate() const
{
return m_releaseDate;
}
bool Movie::setReleaseDate( time_t date )
{
static const std::string req = "UPDATE " + policy::MovieTable::Name
+ " SET release_date = ? WHERE id_movie = ?";
if ( SqliteTools::executeUpdate( m_dbConnection, req, date, m_id ) == false )
return false;
m_releaseDate = date;
return true;
}
const std::string&Movie::shortSummary() const
{
return m_summary;
}
bool Movie::setShortSummary( const std::string& summary )
{
static const std::string req = "UPDATE " + policy::MovieTable::Name
+ " SET summary = ? WHERE id_movie = ?";
if ( SqliteTools::executeUpdate( m_dbConnection, req, summary, m_id ) == false )
return false;
m_summary = summary;
return true;
}
const std::string&Movie::artworkUrl() const
{
return m_artworkUrl;
}
bool Movie::setArtworkUrl( const std::string& artworkUrl )
{
static const std::string req = "UPDATE " + policy::MovieTable::Name
+ " SET artwork_url = ? WHERE id_movie = ?";
if ( SqliteTools::executeUpdate( m_dbConnection, req, artworkUrl, m_id ) == false )
return false;
m_artworkUrl = artworkUrl;
return true;
}
const std::string& Movie::imdbId() const
{
return m_imdbId;
}
bool Movie::setImdbId( const std::string& imdbId )
{
static const std::string req = "UPDATE " + policy::MovieTable::Name
+ " SET imdb_id = ? WHERE id_movie = ?";
if ( SqliteTools::executeUpdate( m_dbConnection, req, imdbId, m_id ) == false )
return false;
m_imdbId = imdbId;
return true;
}
bool Movie::destroy()
{
std::vector<FilePtr> fs;
if ( files( fs ) == false )
return false;
for ( auto& f : fs )
{
File::discard( std::static_pointer_cast<File>( f ) );
}
return _Cache::destroy( m_dbConnection, this );
}
bool Movie::files( std::vector<FilePtr>& files )
{
static const std::string req = "SELECT * FROM " + policy::FileTable::Name
+ " WHERE movie_id = ?";
return SqliteTools::fetchAll<File>( m_dbConnection, req, files, m_id );
}
bool Movie::createTable( sqlite3* dbConnection )
{
static const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::MovieTable::Name
+ "("
"id_movie INTEGER PRIMARY KEY AUTOINCREMENT,"
"title TEXT UNIQUE ON CONFLICT FAIL,"
"release_date UNSIGNED INTEGER,"
"summary TEXT,"
"artwork_url TEXT,"
"imdb_id TEXT"
")";
return SqliteTools::executeRequest( dbConnection, req );
}
MoviePtr Movie::create( sqlite3* dbConnection, const std::string& title )
{
auto movie = std::make_shared<Movie>( title );
static const std::string req = "INSERT INTO " + policy::MovieTable::Name
+ "(title) VALUES(?)";
if ( _Cache::insert( dbConnection, movie, req, title ) == false )
return nullptr;
movie->m_dbConnection = dbConnection;
return movie;
}
#ifndef MOVIE_H
#define MOVIE_H
#include "IMovie.h"
#include <sqlite3.h>
#include "Cache.h"
class Movie;
namespace policy
{
struct MovieTable
{
static const std::string Name;
static const std::string CacheColumn;
static unsigned int Movie::*const PrimaryKey;
};
}
class Movie : public IMovie, public Cache<Movie, IMovie, policy::MovieTable>
{
public:
Movie( sqlite3* dbConnection, sqlite3_stmt* stmt );
Movie( const std::string& title );
virtual unsigned int id() const;
virtual const std::string& title() const;
virtual time_t releaseDate() const;
virtual bool setReleaseDate(time_t date);
virtual const std::string& shortSummary() const;
virtual bool setShortSummary(const std::string& summary);
virtual const std::string& artworkUrl() const;
virtual bool setArtworkUrl(const std::string& artworkUrl);
virtual const std::string& imdbId() const;
virtual bool setImdbId(const std::string& imdbId);
virtual bool destroy();
virtual bool files( std::vector<FilePtr>& files );
static bool createTable( sqlite3* dbConnection );
static MoviePtr create( sqlite3* dbConnection, const std::string& title );
private:
sqlite3* m_dbConnection;
unsigned int m_id;
std::string m_title;
time_t m_releaseDate;
std::string m_summary;
std::string m_artworkUrl;
std::string m_imdbId;
typedef Cache<Movie, IMovie, policy::MovieTable> _Cache;
friend struct policy::MovieTable;
};
#endif // MOVIE_H
......@@ -36,6 +36,7 @@ list(APPEND TEST_SRCS
Albums.cpp
Tests.cpp
Shows.cpp
Movies.cpp
)
add_executable(unittest ${TEST_SRCS})
......
#include "gtest/gtest.h"
#include "IMediaLibrary.h"
#include "IMovie.h"
#include "IFile.h"
class Movies : public testing::Test
{
public:
static IMediaLibrary* ml;
protected:
virtual void SetUp()
{
ml = MediaLibraryFactory::create();
bool res = ml->initialize( "test.db" );
ASSERT_TRUE( res );
}
virtual void TearDown()
{
delete ml;
ml = nullptr;
unlink("test.db");
}
};
IMediaLibrary* Movies::ml;
TEST_F( Movies, Create )
{
auto m = ml->createMovie( "movie" );
ASSERT_NE( m, nullptr );
ASSERT_EQ( m->title(), "movie" );
}
TEST_F( Movies, Fetch )
{
auto m = ml->createMovie( "movie" );
auto m2 = ml->movie( "movie" );
ASSERT_EQ( m, m2 );
delete ml;
SetUp();
m2 = ml->movie( "movie" );
ASSERT_NE( m2, nullptr );
ASSERT_EQ( m2->title(), "movie" );
}
TEST_F( Movies, SetReleaseDate )
{
auto m = ml->createMovie( "movie" );
ASSERT_EQ( m->releaseDate(), 0u );
m->setReleaseDate( 1234 );
ASSERT_EQ( m->releaseDate(), 1234u );
delete ml;
SetUp();
m = ml->movie( "movie" );
ASSERT_EQ( m->releaseDate(), 1234u );
}
TEST_F( Movies, SetShortSummary )
{
auto m = ml->createMovie( "movie" );
ASSERT_EQ( m->shortSummary().length(), 0u );
m->setShortSummary( "great movie" );
ASSERT_EQ( m->shortSummary(), "great movie" );
delete ml;
SetUp();
m = ml->movie( "movie" );
ASSERT_EQ( m->shortSummary(), "great movie" );
}
TEST_F( Movies, SetArtworkUrl )
{
auto m = ml->createMovie( "movie" );
ASSERT_EQ( m->artworkUrl().length(), 0u );
m->setArtworkUrl( "artwork" );
ASSERT_EQ( m->artworkUrl(), "artwork" );
delete ml;
SetUp();
m = ml->movie( "movie" );
ASSERT_EQ( m->artworkUrl(), "artwork" );
}
TEST_F( Movies, SetImdbId )
{
auto m = ml->createMovie( "movie" );
ASSERT_EQ( m->imdbId().length(), 0u );
m->setImdbId( "id" );
ASSERT_EQ( m->imdbId(), "id" );
delete ml;
SetUp();
m = ml->movie( "movie" );
ASSERT_EQ( m->imdbId(), "id" );
}
TEST_F( Movies, AssignToFile )
{
auto f = ml->addFile( "file" );
auto m = ml->createMovie( "movie" );
ASSERT_EQ( f->movie(), nullptr );
f->setMovie( m );
ASSERT_EQ( f->movie(), m );
delete ml;
SetUp();
f = ml->file( "file" );
m = f->movie();
ASSERT_NE( m, nullptr );
ASSERT_EQ( m->title(), "movie" );
}
TEST_F( Movies, DestroyMovie )
{
auto f = ml->addFile( "file" );
auto m = ml->createMovie( "movie" );
f->setMovie( m );
m->destroy();
f = ml->file( "file" );
ASSERT_EQ( f, nullptr );
delete ml;
SetUp();
f = ml->file( "file" );
ASSERT_EQ( f, nullptr );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment