File.cpp 5.37 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*****************************************************************************
 * Media Library
 *****************************************************************************
 * Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
 *
 * Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "File.h"

#include "Media.h"
#include "Folder.h"

const std::string policy::FileTable::Name = "File";
const std::string policy::FileTable::PrimaryKeyColumn = "id_file";
unsigned int File::* const policy::FileTable::PrimaryKey = &File::m_id;

32 33
File::File( MediaLibraryPtr ml, sqlite::Row& row )
    : m_ml( ml )
34 35 36 37 38 39 40 41 42 43 44 45
{
    row >> m_id
        >> m_mediaId
        >> m_mrl
        >> m_type
        >> m_lastModificationDate
        >> m_isParsed
        >> m_folderId
        >> m_isPresent
        >> m_isRemovable;
}

46 47 48
File::File( MediaLibraryPtr ml, unsigned int mediaId, Type type, const fs::IFile& file, unsigned int folderId, bool isRemovable )
    : m_ml( ml )
    , m_id( 0 )
49 50
    , m_mediaId( mediaId )
    , m_mrl( isRemovable == true ? file.name() : file.fullPath() )
51
    , m_type( type )
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
    , m_lastModificationDate( file.lastModificationDate() )
    , m_isParsed( false )
    , m_folderId( folderId )
    , m_isPresent( true )
    , m_isRemovable( isRemovable )
{
}

unsigned int File::id() const
{
    return m_id;
}

const std::string& File::mrl() const
{
    if ( m_isRemovable == false )
        return m_mrl;

    auto lock = m_fullPath.lock();
    if ( m_fullPath.isCached() )
        return m_fullPath;
73
    auto folder = Folder::fetch( m_ml, m_folderId );
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    if ( folder == nullptr )
        return m_mrl;
    m_fullPath = folder->path() + m_mrl;
    return m_fullPath;
}

IFile::Type File::type() const
{
    return m_type;
}

unsigned int File::lastModificationDate() const
{
    return m_lastModificationDate;
}

bool File::isParsed() const
{
    return m_isParsed;
}

std::shared_ptr<Media> File::media() const
{
    auto lock = m_media.lock();
    if ( m_media.isCached() == false )
    {
100
        m_media = Media::fetch( m_ml, m_mediaId );
101
    }
102
    return m_media.get().lock();
103 104 105 106
}

bool File::destroy()
{
107
    return DatabaseHelpers::destroy( m_ml, m_id );
108 109 110 111 112 113 114
}

void File::markParsed()
{
    if ( m_isParsed == true )
        return;
    static const std::string req = "UPDATE " + policy::FileTable::Name + " SET parsed = 1 WHERE id_file = ?";
115
    if ( sqlite::Tools::executeUpdate( m_ml->getConn(), req, m_id ) == false )
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
        return;
    m_isParsed = true;
}

bool File::createTable( DBConnection dbConnection )
{
    std::string req = "CREATE TABLE IF NOT EXISTS " + policy::FileTable::Name + "("
            "id_file INTEGER PRIMARY KEY AUTOINCREMENT,"
            "media_id INT NOT NULL,"
            "mrl TEXT,"
            "type UNSIGNED INTEGER,"
            "last_modification_date UNSIGNED INT,"
            "parsed BOOLEAN NOT NULL DEFAULT 0,"
            "folder_id UNSIGNED INTEGER,"
            "is_present BOOLEAN NOT NULL DEFAULT 1,"
            "is_removable BOOLEAN NOT NULL,"
            "FOREIGN KEY (media_id) REFERENCES " + policy::MediaTable::Name
            + "(id_media) ON DELETE CASCADE,"
            "FOREIGN KEY (folder_id) REFERENCES " + policy::FolderTable::Name
            + "(id_folder) ON DELETE CASCADE,"
            "UNIQUE( mrl, folder_id ) ON CONFLICT FAIL"
        ")";
    std::string triggerReq = "CREATE TRIGGER IF NOT EXISTS is_folder_present AFTER UPDATE OF is_present ON "
            + policy::FolderTable::Name +
            " BEGIN"
            " UPDATE " + policy::FileTable::Name + " SET is_present = new.is_present WHERE folder_id = new.id_folder;"
            " END";
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
143 144
    std::string indexReq = "CREATE INDEX IF NOT EXISTS file_media_id_index ON " +
            policy::FileTable::Name + "(media_id)";
145
    return sqlite::Tools::executeRequest( dbConnection, req ) &&
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
146 147
            sqlite::Tools::executeRequest( dbConnection, triggerReq ) &&
            sqlite::Tools::executeRequest( dbConnection, indexReq );
148 149
}

150
std::shared_ptr<File> File::create( MediaLibraryPtr ml, unsigned int mediaId, Type type, const fs::IFile& fileFs, unsigned int folderId, bool isRemovable )
151
{
152
    auto self = std::make_shared<File>( ml, mediaId, type, fileFs, folderId, isRemovable );
153
    static const std::string req = "INSERT INTO " + policy::FileTable::Name +
154
            "(media_id, mrl, type, folder_id, last_modification_date, is_removable) VALUES(?, ?, ?, ?, ?, ?)";
155

156
    if ( insert( ml, self, req, mediaId, self->m_mrl, type, sqlite::ForeignKey( folderId ),
157 158 159 160 161
                         self->m_lastModificationDate, isRemovable ) == false )
        return nullptr;
    self->m_fullPath = fileFs.fullPath();
    return self;
}