view common/ComposerFileIndex.cpp @ 53:bcea875d8d2f tip

More build fixes
author Chris Cannam
date Thu, 16 Oct 2014 19:03:51 +0100
parents 5f23d5b29aaf
children
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

#include "ComposerFileIndex.h"
#include "TypeRegistrar.h"

#include <QMutexLocker>
#include <QDir>

#include "base/TempDirectory.h"
#include "base/Exceptions.h"

using namespace Dataquay;


namespace ClassicalData {

ComposerFileIndex *
ComposerFileIndex::getInstance()
{
    static ComposerFileIndex instance;
    return &instance;
}

ComposerFileIndex::ComposerFileIndex() :
    m_bs(0),
    m_index(0)
{
    try {
	m_indexFileName = getIndexFileName();
    } catch (DirectoryCreationFailed f) {
        std::cerr << "ComposerFileIndex: ERROR: Failed to find or create index directory: " << f.what() << std::endl;
        return;
    }

    m_bs = new BasicStore;
    m_index = new TransactionalStore(m_bs);

    TypeRegistrar::addMappings(m_bs, 0);

    if (QFile(m_indexFileName).exists()) {
	m_bs->import(QUrl::fromLocalFile(m_indexFileName),
                     BasicStore::ImportIgnoreDuplicates);
	//!!! catch
    }
}

ComposerFileIndex::~ComposerFileIndex()
{
    delete m_index;
    delete m_bs;
}

QString
ComposerFileIndex::getIndexFileName()
{
    QDir d = TempDirectory::getInstance()->getContainingPath();
    QString n("index");
    QFileInfo fi(d.filePath(n));

    if ((fi.exists() && !fi.isDir()) ||
        (!fi.exists() && !d.mkdir(n))) {
        throw DirectoryCreationFailed(fi.filePath());
    }

    return QDir(fi.filePath()).filePath("composer-details.ttl");
}

QString
ComposerFileIndex::getComposerDirectoryName()
{
    QDir d = TempDirectory::getInstance()->getContainingPath();
    QString n("composers");
    QFileInfo fi(d.filePath(n));

    if ((fi.exists() && !fi.isDir()) ||
        (!fi.exists() && !d.mkdir(n))) {
        throw DirectoryCreationFailed(fi.filePath());
    }

    return fi.filePath();
}

void
ComposerFileIndex::loadFor(Uri composerUri, Store *store)
{
    if (!m_index) {
	std::cerr << "ComposerFileIndex::loadFor: No index!" << std::endl;
	return;
    }
    updateIndex();

    Triple pattern(Node(), "foaf:primaryTopic", composerUri);
    Triples results = m_index->match(pattern);
    std::cerr << "ComposerFileIndex::loadFor: " << results.size() << " file(s) for composer " << composerUri << std::endl;

    bool loadedSomething = false;

    foreach (Triple t, results) {
        try {
            BasicStore *b = BasicStore::load(QUrl(t.a.value));
            //!!! This is hardly the most efficient!
            Triples all = b->match(Triple());
            //!!! There is no Store::add(Triples)
            foreach (Triple t, all) {
                store->add(t);
            }
        } catch (...) { } //!!!???
    }

    return loadedSomething;
}

void
ComposerFileIndex::composerFileAdded(QString filepath)
{
    index(QUrl::fromLocalFile(filepath));
}    

void
ComposerFileIndex::updateIndex()
{
    QMutexLocker locker(&m_mutex);
    if (!m_index) return;

    std::cerr << "Generating index..." << std::endl;

    QDir composerDir;
    try {
	QString s = getComposerDirectoryName();
        composerDir = QDir(s);
    } catch (DirectoryCreationFailed f) {
        std::cerr << "ComposerFileIndex::updateIndex: ERROR: Failed to find or create composer directory: " << f.what() << std::endl;
        return;
    }

    composerDir.setFilter(QDir::Files);

    for (unsigned int i = 0; i < composerDir.count(); ++i) {
        QFileInfo fi(composerDir.filePath(composerDir[i]));
        if (fi.isFile() && fi.isReadable()) {
            index(QUrl::fromLocalFile(fi.filePath()));
        }
    }

    //!!! remove triples from index that refer to nonexistent files?

    std::cerr << "Saving index to " << m_indexFileName.toStdString() << std::endl;
    m_bs->save(m_indexFileName);

    std::cerr << "Done" << std::endl;
}

void
ComposerFileIndex::index(QUrl fileUrl)
{
    Triple typeTriple(Uri(fileUrl), "a", m_index->expand("foaf:Document"));

    if (m_index->contains(typeTriple)) {
        return;
    }

    Transaction *tx = m_index->startTransaction();
    tx->add(typeTriple);

    try {
        BasicStore *b = BasicStore::load(fileUrl);
        Triples ts = b->match
            (Triple(Node(), "a", m_index->expand("classical:Composer")));
        foreach (Triple t, ts) {
            tx->add(Triple(Uri(fileUrl), "foaf:primaryTopic", t.a));;
        }
    } catch (std::exception &e) {
        std::cerr << "Caught exception: \"" << e.what() << "\" while indexing "
                  << Uri(fileUrl) << ", skipping" << std::endl;
    }
    
    tx->commit();
    delete tx;
}


}