changeset 725:c789deb83bd4 dataquay

Convert PluginRDFDescription and PluginRDFIndexer to use Dataquay
author Chris Cannam
date Fri, 18 May 2012 14:45:15 +0100
parents 7eb389da7976
children 1bfb40549003
files rdf/PluginRDFDescription.cpp rdf/PluginRDFIndexer.cpp rdf/PluginRDFIndexer.h svcore.pro
diffstat 4 files changed, 155 insertions(+), 276 deletions(-) [+]
line wrap: on
line diff
--- a/rdf/PluginRDFDescription.cpp	Fri May 18 09:48:19 2012 +0100
+++ b/rdf/PluginRDFDescription.cpp	Fri May 18 14:45:15 2012 +0100
@@ -16,16 +16,24 @@
 #include "PluginRDFDescription.h"
 
 #include "PluginRDFIndexer.h"
-#include "SimpleSPARQLQuery.h"
 
 #include "base/Profiler.h"
 
 #include "plugin/PluginIdentifier.h"
 
+#include <dataquay/BasicStore.h>
+
 #include <iostream>
 using std::cerr;
 using std::endl;
 
+using Dataquay::Uri;
+using Dataquay::Node;
+using Dataquay::Nodes;
+using Dataquay::Triple;
+using Dataquay::Triples;
+using Dataquay::BasicStore;
+
 PluginRDFDescription::PluginRDFDescription(QString pluginId) :
     m_pluginId(pluginId),
     m_haveDescription(false)
@@ -172,93 +180,42 @@
 {
     Profiler profiler("PluginRDFDescription::index");
 
-    SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
+    PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
+    const BasicStore *index = indexer->getIndex();
+    Uri plugin(m_pluginUri);
 
-    QString queryTemplate =
-        QString(
-            " PREFIX vamp: <http://purl.org/ontology/vamp/> "
-            " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
-            " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
-            " SELECT ?%3 "
-            " WHERE { "
-            "   <%1> %2 ?%3 . "
-            " }")
-        .arg(m_pluginUri);
-
-    SimpleSPARQLQuery::Value v;
-
-    v = SimpleSPARQLQuery::singleResultQuery
-        (m, queryTemplate.arg("vamp:name").arg("name"), "name");
-    
-    if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
-        m_pluginName = v.value;
+    Node n = index->matchFirst(Triple(plugin, "vamp:name", Node())).c;
+    if (n.type == Node::Literal && n.value != "") {
+        m_pluginName = n.value;
     }
 
-    v = SimpleSPARQLQuery::singleResultQuery
-        (m, queryTemplate.arg("dc:description").arg("description"), "description");
-    
-    if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
-        m_pluginDescription = v.value;
+    n = index->matchFirst(Triple(plugin, "dc:description", Node())).c;
+    if (n.type == Node::Literal && n.value != "") {
+        m_pluginDescription = n.value;
     }
 
-    v = SimpleSPARQLQuery::singleResultQuery
-        (m,
-         QString(
-            " PREFIX vamp: <http://purl.org/ontology/vamp/> "
-            " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
-            " SELECT ?name "
-            " WHERE { "
-            "   <%1> foaf:maker ?maker . "
-            "   ?maker foaf:name ?name . "
-            " }")
-         .arg(m_pluginUri),
-         "name");
-    
-    if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
-        m_pluginMaker = v.value;
+    n = index->matchFirst(Triple(plugin, "foaf:maker", Node())).c;
+    if (n.type == Node::URI || n.type == Node::Blank) {
+        n = index->matchFirst(Triple(n, "foaf:name", Node())).c;
+        if (n.type == Node::Literal && n.value != "") {
+            m_pluginMaker = n.value;
+        }
     }
 
     // If we have a more-information URL for this plugin, then we take
-    // that.  Otherwise, a more-information URL for the plugin
-    // library would do nicely.  Failing that, we could perhaps use
-    // any foaf:page URL at all that appears in the file -- but
-    // perhaps that would be unwise
+    // that.  Otherwise, a more-information URL for the plugin library
+    // would do nicely.
 
-    v = SimpleSPARQLQuery::singleResultQuery
-        (m,
-         QString(
-            " PREFIX vamp: <http://purl.org/ontology/vamp/> "
-            " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
-            " SELECT ?page "
-            " WHERE { "
-            "   <%1> foaf:page ?page . "
-            " }")
-         .arg(m_pluginUri),
-         "page");
+    n = index->matchFirst(Triple(plugin, "foaf:page", Node())).c;
+    if (n.type == Node::URI && n.value != "") {
+        m_pluginInfoURL = n.value;
+    }
 
-    if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
-
-        m_pluginInfoURL = v.value;
-
-    } else {
-
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m,
-             QString(
-                " PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                " PREFIX foaf: <http://xmlns.com/foaf/0.1/> "
-                " SELECT ?page "
-                " WHERE { "
-                "   ?library vamp:available_plugin <%1> ; "
-                "            a vamp:PluginLibrary ; "
-                "            foaf:page ?page . "
-                " }")
-             .arg(m_pluginUri),
-             "page");
-
-        if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
-
-            m_pluginInfoURL = v.value;
+    n = index->matchFirst(Triple(Node(), "vamp:available_plugin", plugin)).a;
+    if (n.value != "") {
+        n = index->matchFirst(Triple(n, "foaf:page", Node())).c;
+        if (n.type == Node::URI && n.value != "") {
+            m_pluginInfoURL = n.value;
         }
     }
 
@@ -270,87 +227,42 @@
 {
     Profiler profiler("PluginRDFDescription::indexOutputs");
     
-    SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
+    PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
+    const BasicStore *index = indexer->getIndex();
+    Uri plugin(m_pluginUri);
 
-    SimpleSPARQLQuery query
-        (m,
-         QString
-         (
-             " PREFIX vamp: <http://purl.org/ontology/vamp/> "
+    Nodes outputs = index->match(Triple(plugin, "vamp:output", Node())).a();
 
-             " SELECT ?output "
-
-             " WHERE { "
-             "   <%1> vamp:output ?output . "
-             " } "
-             )
-         .arg(m_pluginUri));
-
-    SimpleSPARQLQuery::ResultList results = query.execute();
-
-    if (!query.isOK()) {
-        cerr << "ERROR: PluginRDFDescription::index: ERROR: Failed to query outputs for <"
-             << m_pluginUri << ">: "
-             << query.getErrorString() << endl;
-        return false;
-    }
-
-    if (results.empty()) {
+    if (outputs.empty()) {
         cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: No outputs defined for <"
              << m_pluginUri << ">" << endl;
         return false;
     }
 
-    // Note that an output may appear more than once, if it inherits
-    // more than one type (e.g. DenseOutput and QuantizedOutput).  So
-    // these results must accumulate
+    foreach (Node output, outputs) {
 
-    for (int i = 0; i < results.size(); ++i) {
-
-        if (results[i]["output"].type != SimpleSPARQLQuery::URIValue ||
-            results[i]["output"].value == "") {
-            cerr << "ERROR: PluginRDFDescription::indexURL: No valid URI for output " << i << " of plugin <" << m_pluginUri << ">" << endl;
+        if ((output.type != Node::URI && output.type != Node::Blank) ||
+            output.value == "") {
+            cerr << "ERROR: PluginRDFDescription::indexURL: No valid URI for output " << output << " of plugin <" << m_pluginUri << ">" << endl;
             return false;
         }
-
-        QString outputUri = results[i]["output"].value;
-
-        SimpleSPARQLQuery::Value v;
-
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, 
-             QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                     " SELECT ?output_id "
-                     " WHERE { <%1> vamp:identifier ?output_id } ")
-             .arg(outputUri), "output_id");
-
-        if (v.type != SimpleSPARQLQuery::LiteralValue || v.value == "") {
-            cerr << "ERROR: PluginRDFDescription::indexURL: No identifier for output <" << outputUri << ">" << endl;
+        
+        Node n = index->matchFirst(Triple(output, "vamp:identifier", Node())).c;
+        if (n.type != Node::Literal || n.value == "") {
+            cerr << "ERROR: PluginRDFDescription::indexURL: No vamp:identifier for output <" << output << ">" << endl;
             return false;
         }
-        QString outputId = v.value;
+        QString outputId = n.value;
 
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, 
-             QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                     " SELECT ?output_type "
-                     " WHERE { <%1> a ?output_type } ")
-             .arg(outputUri), "output_type");
+        n = index->matchFirst(Triple(output, "a", Node())).c;
+        QString outputType;
+        if (n.type == Node::URI) outputType = n.value;
 
-        QString outputType;
-        if (v.type == SimpleSPARQLQuery::URIValue) outputType = v.value;
+        n = index->matchFirst(Triple(output, "vamp:unit", Node())).c;
+        QString outputUnit;
+        if (n.type == Node::Literal) outputUnit = n.value;
 
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, 
-             QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                     " SELECT ?unit "
-                     " WHERE { <%1> vamp:unit ?unit } ")
-             .arg(outputUri), "unit");
-
-        QString outputUnit;
-        if (v.type == SimpleSPARQLQuery::LiteralValue) outputUnit = v.value;
-
-        m_outputUriMap[outputId] = outputUri;
+        m_outputUriMap[outputId] = output.value;
 
         if (outputType.contains("DenseOutput")) {
             m_outputDispositions[outputId] = OutputDense;
@@ -366,43 +278,24 @@
             m_outputUnitMap[outputId] = outputUnit;
         }
 
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, 
-             QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                     " PREFIX dc: <http://purl.org/dc/elements/1.1/> "
-                     " SELECT ?title "
-                     " WHERE { <%1> dc:title ?title } ")
-             .arg(outputUri), "title");
-
-        if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
-            m_outputNames[outputId] = v.value;
+        n = index->matchFirst(Triple(output, "dc:title", Node())).c;
+        if (n.type == Node::Literal && n.value != "") {
+            m_outputNames[outputId] = n.value;
         }
 
-        QString queryTemplate = 
-            QString(" PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                    " SELECT ?%2 "
-                    " WHERE { <%1> vamp:computes_%2 ?%2 } ")
-            .arg(outputUri);
-
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, queryTemplate.arg("event_type"), "event_type");
-
-        if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
-            m_outputEventTypeURIMap[outputId] = v.value;
+        n = index->matchFirst(Triple(output, "vamp:computes_event_type", Node())).c;
+        if (n.type == Node::URI && n.value != "") {
+            m_outputEventTypeURIMap[outputId] = n.value;
         }
 
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, queryTemplate.arg("feature"), "feature");
+        n = index->matchFirst(Triple(output, "vamp:computes_feature", Node())).c;
+        if (n.type == Node::URI && n.value != "") {
+            m_outputFeatureAttributeURIMap[outputId] = n.value;
+        }
 
-        if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
-            m_outputFeatureAttributeURIMap[outputId] = v.value;
-        }           
-
-        v = SimpleSPARQLQuery::singleResultQuery
-            (m, queryTemplate.arg("signal_type"), "signal_type");
-
-        if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
-            m_outputSignalTypeURIMap[outputId] = v.value;
+        n = index->matchFirst(Triple(output, "vamp:computes_signal_type", Node())).c;
+        if (n.type == Node::URI && n.value != "") {
+            m_outputSignalTypeURIMap[outputId] = n.value;
         }
     }
 
--- a/rdf/PluginRDFIndexer.cpp	Fri May 18 09:48:19 2012 +0100
+++ b/rdf/PluginRDFIndexer.cpp	Fri May 18 14:45:15 2012 +0100
@@ -15,8 +15,6 @@
 
 #include "PluginRDFIndexer.h"
 
-#include "SimpleSPARQLQuery.h"
-
 #include "data/fileio/CachedFile.h"
 #include "data/fileio/FileSource.h"
 #include "data/fileio/PlaylistFileReader.h"
@@ -26,6 +24,9 @@
 
 #include <vamp-hostsdk/PluginHostAdapter.h>
 
+#include <dataquay/BasicStore.h>
+#include <dataquay/RDFException.h>
+
 #include <QFileInfo>
 #include <QDir>
 #include <QUrl>
@@ -40,12 +41,18 @@
 using std::string;
 using Vamp::PluginHostAdapter;
 
+using Dataquay::Uri;
+using Dataquay::Node;
+using Dataquay::Nodes;
+using Dataquay::Triple;
+using Dataquay::Triples;
+using Dataquay::BasicStore;
+using Dataquay::RDFException;
+using Dataquay::RDFDuplicateImportException;
+
 PluginRDFIndexer *
 PluginRDFIndexer::m_instance = 0;
 
-bool
-PluginRDFIndexer::m_prefixesLoaded = false;
-
 PluginRDFIndexer *
 PluginRDFIndexer::getInstance() 
 {
@@ -53,11 +60,21 @@
     return m_instance;
 }
 
-PluginRDFIndexer::PluginRDFIndexer()
+PluginRDFIndexer::PluginRDFIndexer() :
+    m_index(new Dataquay::BasicStore)
 {
+    m_index->addPrefix("vamp", Uri("http://purl.org/ontology/vamp/"));
+    m_index->addPrefix("foaf", Uri("http://xmlns.com/foaf/0.1/"));
+    m_index->addPrefix("dc", Uri("http://purl.org/dc/elements/1.1/"));
     indexInstalledURLs();
 }
 
+const BasicStore *
+PluginRDFIndexer::getIndex()
+{
+    return m_index;
+}
+
 PluginRDFIndexer::~PluginRDFIndexer()
 {
     QMutexLocker locker(&m_mutex);
@@ -241,13 +258,11 @@
 {
     Profiler profiler("PluginRDFIndexer::indexURL");
 
-    loadPrefixes();
-
 //    SVDEBUG << "PluginRDFIndexer::indexURL(" << urlString << ")" << endl;
 
     QMutexLocker locker(&m_mutex);
 
-    QString localString = urlString;
+    QUrl local = urlString;
 
     if (FileSource::isRemote(urlString) &&
         FileSource::canHandleScheme(urlString)) {
@@ -257,91 +272,76 @@
             return false;
         }
 
-        localString = QUrl::fromLocalFile(cf.getLocalFilename()).toString();
+        local = QUrl::fromLocalFile(cf.getLocalFilename());
+
+    } else {
+
+        local = QUrl::fromLocalFile(urlString);
     }
 
-    return SimpleSPARQLQuery::addSourceToModel(localString);
+    try {
+        m_index->import(local, BasicStore::ImportFailOnDuplicates);
+    } catch (RDFDuplicateImportException &e) {
+        cerr << "PluginRDFIndexer::pullURL: Document at " << urlString
+             << " duplicates triples found in earlier loaded document" << endl;
+        return false;
+    } catch (RDFException &e) {
+        cerr << "PluginRDFIndexer::pullURL: Failed to import document from "
+             << urlString << ": " << e.what() << endl;
+        return false;
+    }
+    return true;
 }
 
 bool
 PluginRDFIndexer::reindex()
 {
-    SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
-
-    SimpleSPARQLQuery query
-        (m,
-         QString
-         (
-             " PREFIX vamp: <http://purl.org/ontology/vamp/> "
-
-             " SELECT ?plugin ?library ?plugin_id "
-
-             " WHERE { "
-             "   ?plugin a vamp:Plugin . "
-             "   ?plugin vamp:identifier ?plugin_id . "
-
-             "   OPTIONAL { "
-             "     ?library vamp:available_plugin ?plugin "
-             "   } "
-             " } "
-             ));
-
-    SimpleSPARQLQuery::ResultList results = query.execute();
-
-    if (!query.isOK()) {
-        cerr << "ERROR: PluginRDFIndexer::reindex: ERROR: Failed to query plugins from model: "
-             << query.getErrorString() << endl;
-        return false;
-    }
-
-    if (results.empty()) {
-        cerr << "PluginRDFIndexer::reindex: NOTE: no vamp:Plugin resources found in indexed documents" << endl;
-        return false;
-    }
+    Triples tt = m_index->match
+        (Triple(Node(), "a", m_index->expand("vamp:Plugin")));
+    Nodes plugins = tt.a();
 
     bool foundSomething = false;
     bool addedSomething = false;
 
-    for (SimpleSPARQLQuery::ResultList::iterator i = results.begin();
-         i != results.end(); ++i) {
-
-        QString pluginUri = (*i)["plugin"].value;
-        QString soUri = (*i)["library"].value;
-        QString identifier = (*i)["plugin_id"].value;
-
-        if (identifier == "") {
-            cerr << "PluginRDFIndexer::reindex: NOTE: No vamp:identifier for plugin <"
-                 << pluginUri << ">"
-                 << endl;
+    foreach (Node plugin, plugins) {
+        
+        if (plugin.type != Node::URI) {
+            cerr << "PluginRDFIndexer::reindex: Plugin has no URI: node is "
+                 << plugin << endl;
             continue;
         }
-        if (soUri == "") {
-            cerr << "PluginRDFIndexer::reindex: NOTE: No implementation library for plugin <"
-                 << pluginUri << ">"
-                 << endl;
+        
+        Triple idt = m_index->matchFirst
+            (Triple(plugin, "vamp:identifier", Node()));
+        
+        if (idt.c.type != Node::Literal) {
+            cerr << "PluginRDFIndexer::reindex: Plugin " << plugin
+                 << " lacks vamp:identifier literal" << endl;
             continue;
         }
 
-        QString sonameQuery =
-            QString(
-                " PREFIX vamp: <http://purl.org/ontology/vamp/> "
-                " SELECT ?library_id "
-                " WHERE { "
-                "   <%1> vamp:identifier ?library_id "
-                " } "
-                )
-            .arg(soUri);
+        Triple libt = m_index->matchFirst
+            (Triple(Node(), "vamp:available_plugin", plugin));
 
-        SimpleSPARQLQuery::Value sonameValue = 
-            SimpleSPARQLQuery::singleResultQuery(m, sonameQuery, "library_id");
-        QString soname = sonameValue.value;
-        if (soname == "") {
-            cerr << "PluginRDFIndexer::reindex: NOTE: No identifier for library <"
-                 << soUri << ">"
-                 << endl;
+        if (libt.a.type != Node::URI) {
+            cerr << "PluginRDFIndexer::reindex: Plugin " << plugin 
+                 << " is not vamp:available_plugin in any library" << endl;
             continue;
         }
 
+        Triple sot = m_index->matchFirst
+            (Triple(libt.a, "vamp:identifier", Node()));
+
+        if (sot.c.type != Node::Literal) {
+            cerr << "PluginRDFIndexer::reindex: Library " << libt.a
+                 << " lacks vamp:identifier for soname" << endl;
+            continue;
+        }
+
+        QString pluginUri = plugin.value;
+        QString identifier = idt.c.value;
+        QString soname = sot.c.value;
+
         QString pluginId = PluginIdentifier::createIdentifier
             ("vamp", soname, identifier);
 
@@ -373,23 +373,3 @@
     
     return addedSomething;
 }
-
-void
-PluginRDFIndexer::loadPrefixes()
-{
-    return;
-//!!!
-    if (m_prefixesLoaded) return;
-    const char *prefixes[] = {
-        "http://purl.org/ontology/vamp/"
-    };
-    for (size_t i = 0; i < sizeof(prefixes)/sizeof(prefixes[0]); ++i) {
-        CachedFile cf(prefixes[i], 0, "application/rdf+xml");
-        if (!cf.isOK()) continue;
-        SimpleSPARQLQuery::addSourceToModel
-            (QUrl::fromLocalFile(cf.getLocalFilename()).toString());
-    }
-    m_prefixesLoaded = true;
-}
-
-
--- a/rdf/PluginRDFIndexer.h	Fri May 18 09:48:19 2012 +0100
+++ b/rdf/PluginRDFIndexer.h	Fri May 18 14:45:15 2012 +0100
@@ -22,6 +22,10 @@
 #include <map>
 #include <set>
 
+namespace Dataquay {
+    class BasicStore;
+}
+
 class PluginRDFIndexer
 {
 public:
@@ -48,6 +52,8 @@
 
     QStringList getIndexedPluginIds();
 
+    const Dataquay::BasicStore *getIndex();
+
     ~PluginRDFIndexer();
 
 protected:
@@ -64,8 +70,8 @@
     bool pullURL(QString urlString);
     bool reindex();
 
-    static void loadPrefixes();
-    static bool m_prefixesLoaded;
+    Dataquay::BasicStore *m_index;
+
     static PluginRDFIndexer *m_instance;
 };
 
--- a/svcore.pro	Fri May 18 09:48:19 2012 +0100
+++ b/svcore.pro	Fri May 18 14:45:15 2012 +0100
@@ -230,15 +230,15 @@
            plugin/api/dssi_alsa_compat.c \
            plugin/plugins/SamplePlayer.cpp
 
-HEADERS += rdf/PluginRDFDescription.h \
-           rdf/PluginRDFIndexer.h \
+HEADERS += rdf/PluginRDFIndexer.h \
+           rdf/PluginRDFDescription.h \
            rdf/RDFExporter.h \
            rdf/RDFFeatureWriter.h \
            rdf/RDFImporter.h \
            rdf/RDFTransformFactory.h \
            rdf/SimpleSPARQLQuery.h
-SOURCES += rdf/PluginRDFDescription.cpp \
-           rdf/PluginRDFIndexer.cpp \
+SOURCES += rdf/PluginRDFIndexer.cpp \
+           rdf/PluginRDFDescription.cpp \
            rdf/RDFExporter.cpp \
            rdf/RDFFeatureWriter.cpp \
            rdf/RDFImporter.cpp \