diff rdf/RDFTransformFactory.cpp @ 489:82ab61fa9223

* Reorganise our sparql queries on the basis that Redland must be available, not only optional. So for anything querying the pool of data about plugins, we use a single datastore and model which is initialised at the outset by PluginRDFIndexer and then queried directly; for anything that "reads from a file" (e.g. loading annotations) we query directly using Rasqal, going to the datastore when we need additional plugin-related information. This may improve performance, but mostly it simplifies the code and fixes a serious issue with RDF import in the previous versions (namely that multiple sequential RDF imports would end up sharing the same RDF data pool!)
author Chris Cannam
date Fri, 21 Nov 2008 16:12:29 +0000
parents 3ffce691c9bf
children 23945cdd7161
line wrap: on
line diff
--- a/rdf/RDFTransformFactory.cpp	Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/RDFTransformFactory.cpp	Fri Nov 21 16:12:29 2008 +0000
@@ -47,8 +47,8 @@
 protected:
     QString m_urlString;
     QString m_errorString;
-    bool setOutput(Transform &, QString, QString);
-    bool setParameters(Transform &, QString, QString);
+    bool setOutput(Transform &, QString);
+    bool setParameters(Transform &, QString);
 };
 
 
@@ -112,38 +112,22 @@
 {
     std::vector<Transform> transforms;
 
-    // We have to do this a very long way round, to work around
-    // rasqal's current inability to handle correctly more than one
-    // OPTIONAL graph in a query
-
-    const char *optionals[] = {
-        "output",
-        "program",
-        "step_size",
-        "block_size",
-        "window_type",
-        "sample_rate",
-        "start", 
-        "duration"
-    };
-
     std::map<QString, Transform> uriTransformMap;
 
-    QString queryTemplate = 
+    QString query = 
         " PREFIX vamp: <http://purl.org/ontology/vamp/> "
 
-        " SELECT ?transform ?plugin %1 "
+        " SELECT ?transform ?plugin "
         
         " FROM <%2> "
 
         " WHERE { "
         "   ?transform a vamp:Transform ; "
         "              vamp:plugin ?plugin . "
-        "   %3 "
         " } ";
 
     SimpleSPARQLQuery transformsQuery
-        (m_urlString, queryTemplate.arg("").arg(m_urlString).arg(""));
+        (SimpleSPARQLQuery::QueryFromSingleSource, query.arg(m_urlString));
 
     SimpleSPARQLQuery::ResultList transformResults = transformsQuery.execute();
 
@@ -157,6 +141,17 @@
         return transforms;
     }
 
+    // There are various queries we need to make that might include
+    // data from iether the transform RDF or the model accumulated
+    // from plugin descriptions.  For example, the transform RDF may
+    // specify the output's true URI, or it might have a blank node or
+    // some other URI with the appropriate vamp:identifier included in
+    // the file.  To cover both cases, we need to add the file itself
+    // into the model and always query the model using the transform
+    // URI rather than querying the file itself subsequently.
+
+    SimpleSPARQLQuery::addSourceToModel(m_urlString);
+
     PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
 
     for (int i = 0; i < transformResults.size(); ++i) {
@@ -175,93 +170,89 @@
             continue;
         }
 
-        QString pluginDescriptionURL =
-            indexer->getDescriptionURLForPluginId(pluginId);
-        if (pluginDescriptionURL == "") {
-            cerr << "RDFTransformFactory: WARNING: No RDF description available for plugin <"
-                 << pluginUri.toStdString() << ">, skipping transform <"
-                 << transformUri.toStdString() << ">" << endl;
-            continue;
-        }
-
         Transform transform;
         transform.setPluginIdentifier(pluginId);
 
-        if (!setOutput(transform, transformUri, pluginDescriptionURL)) {
+        if (!setOutput(transform, transformUri)) {
             return transforms;
         }
 
-        if (!setParameters(transform, transformUri, pluginDescriptionURL)) {
+        if (!setParameters(transform, transformUri)) {
             return transforms;
         }
 
         uriTransformMap[transformUri] = transform;
-    }
 
-    for (int i = 0; i < sizeof(optionals)/sizeof(optionals[0]); ++i) {
+        // We have to do this a very long way round, to work around
+        // rasqal's current inability to handle correctly more than one
+        // OPTIONAL graph in a query
 
-        QString optional = optionals[i];
+        static const char *optionals[] = {
+            "output",
+            "program",
+            "step_size",
+            "block_size",
+            "window_type",
+            "sample_rate",
+            "start", 
+            "duration"
+        };
+        
+        for (int j = 0; j < sizeof(optionals)/sizeof(optionals[0]); ++j) {
 
-        SimpleSPARQLQuery query
-            (m_urlString,
-             queryTemplate
-             .arg(QString("?%1").arg(optional))
-             .arg(m_urlString)
-             .arg(QString("?transform vamp:%1 ?%2")
-                  .arg(optionals[i]).arg(optional)));
+            QString optional = optionals[j];
+
+            QString queryTemplate = 
+                " PREFIX vamp: <http://purl.org/ontology/vamp/> "
+                
+                " SELECT ?%1 "
+                
+                " WHERE { "
+                "   <%2> vamp:%1 ?%1 "
+                " } ";
+            
+            SimpleSPARQLQuery query
+                (SimpleSPARQLQuery::QueryFromModel,
+                 queryTemplate.arg(optional).arg(transformUri));
         
-        SimpleSPARQLQuery::ResultList results = query.execute();
+            SimpleSPARQLQuery::ResultList results = query.execute();
 
-        if (!query.isOK()) {
-            m_errorString = query.getErrorString();
-            return transforms;
-        }
-
-        if (results.empty()) continue;
-
-        for (int j = 0; j < results.size(); ++j) {
-
-            QString transformUri = results[j]["transform"].value;
-            
-            if (uriTransformMap.find(transformUri) == uriTransformMap.end()) {
-                cerr << "RDFTransformFactory: ERROR: Transform URI <"
-                     << transformUri.toStdString() << "> not found in internal map!" << endl;
-                continue;
+            if (!query.isOK()) {
+                m_errorString = query.getErrorString();
+                return transforms;
             }
 
-            Transform &transform = uriTransformMap[transformUri];
-            const SimpleSPARQLQuery::Value &v = results[j][optional];
+            if (results.empty()) continue;
 
-            if (v.type == SimpleSPARQLQuery::LiteralValue) {
+            for (int k = 0; k < results.size(); ++k) {
+
+                const SimpleSPARQLQuery::Value &v = results[k][optional];
+
+                if (v.type == SimpleSPARQLQuery::LiteralValue) {
                 
-                if (optional == "program") {
-                    transform.setProgram(v.value);
-                } else if (optional == "step_size") {
-                    transform.setStepSize(v.value.toUInt());
-                } else if (optional == "block_size") {
-                    transform.setBlockSize(v.value.toUInt());
-                } else if (optional == "window_type") {
-                    cerr << "NOTE: can't handle window type yet (value is \""
-                         << v.value.toStdString() << "\")" << endl;
-                } else if (optional == "sample_rate") {
-                    transform.setSampleRate(v.value.toFloat());
-                } else if (optional == "start") {
-                    transform.setStartTime
-                        (RealTime::fromXsdDuration(v.value.toStdString()));
-                } else if (optional == "duration") {
-                    transform.setDuration
-                        (RealTime::fromXsdDuration(v.value.toStdString()));
-                } else {
-                    cerr << "RDFTransformFactory: ERROR: Inconsistent optionals lists (unexpected optional \"" << optional.toStdString() << "\"" << endl;
+                    if (optional == "program") {
+                        transform.setProgram(v.value);
+                    } else if (optional == "step_size") {
+                        transform.setStepSize(v.value.toUInt());
+                    } else if (optional == "block_size") {
+                        transform.setBlockSize(v.value.toUInt());
+                    } else if (optional == "window_type") {
+                        cerr << "NOTE: can't handle window type yet (value is \""
+                             << v.value.toStdString() << "\")" << endl;
+                    } else if (optional == "sample_rate") {
+                        transform.setSampleRate(v.value.toFloat());
+                    } else if (optional == "start") {
+                        transform.setStartTime
+                            (RealTime::fromXsdDuration(v.value.toStdString()));
+                    } else if (optional == "duration") {
+                        transform.setDuration
+                            (RealTime::fromXsdDuration(v.value.toStdString()));
+                    } else {
+                        cerr << "RDFTransformFactory: ERROR: Inconsistent optionals lists (unexpected optional \"" << optional.toStdString() << "\"" << endl;
+                    }
                 }
             }
         }
-    }
-
-    for (std::map<QString, Transform>::iterator i = uriTransformMap.begin();
-         i != uriTransformMap.end(); ++i) {
-
-        Transform &transform = i->second;
 
         cerr << "RDFTransformFactory: NOTE: Transform is: " << endl;
         cerr << transform.toXmlString().toStdString() << endl;
@@ -274,45 +265,55 @@
 
 bool
 RDFTransformFactoryImpl::setOutput(Transform &transform,
-                                   QString transformUri,
-                                   QString pluginDescriptionURL)
+                                   QString transformUri)
 {
-    SimpleSPARQLQuery outputQuery
-        (m_urlString,
+    SimpleSPARQLQuery::Value outputValue =
+        SimpleSPARQLQuery::singleResultQuery
+        (SimpleSPARQLQuery::QueryFromModel,
+         QString
+         (
+             " PREFIX vamp: <http://purl.org/ontology/vamp/> "
+             
+             " SELECT ?output "
+
+             " WHERE { "
+             "   <%1> vamp:output ?output . "
+             " } "
+             )
+         .arg(transformUri),
+         "output");
+    
+    if (outputValue.type == SimpleSPARQLQuery::NoValue) {
+        return true;
+    }
+
+    if (outputValue.type != SimpleSPARQLQuery::URIValue) {
+        m_errorString = "No vamp:output given, or not a URI";
+        return false;
+    }
+
+    SimpleSPARQLQuery::Value outputIdValue =
+        SimpleSPARQLQuery::singleResultQuery
+        (SimpleSPARQLQuery::QueryFromModel,
          QString
          (
              " PREFIX vamp: <http://purl.org/ontology/vamp/> "
              
              " SELECT ?output_id "
              
-             " FROM <%1> "
-             " FROM <%2> "
-             
              " WHERE { "
-             "   <%3> vamp:output ?output . "
-             "   ?output vamp:identifier ?output_id "
+             "   <%1> vamp:identifier ?output_id "
              " } "
              )
-         .arg(m_urlString)
-         .arg(pluginDescriptionURL)
-         .arg(transformUri));
+         .arg(outputValue.value),
+         "output_id");
     
-    SimpleSPARQLQuery::ResultList outputResults = outputQuery.execute();
-    
-    if (!outputQuery.isOK()) {
-        m_errorString = outputQuery.getErrorString();
+    if (outputIdValue.type != SimpleSPARQLQuery::LiteralValue) {
+        m_errorString = "No output vamp:identifier available, or not a literal";
         return false;
     }
-    
-    if (outputQuery.wasCancelled()) {
-        m_errorString = "Query cancelled";
-        return false;
-    }
-    
-    for (int j = 0; j < outputResults.size(); ++j) {
-        QString outputId = outputResults[j]["output_id"].value;
-        transform.setOutput(outputId);
-    }
+
+    transform.setOutput(outputIdValue.value);
 
     return true;
 }
@@ -320,29 +321,23 @@
 
 bool
 RDFTransformFactoryImpl::setParameters(Transform &transform,
-                                       QString transformUri,
-                                       QString pluginDescriptionURL)
+                                       QString transformUri)
 {
     SimpleSPARQLQuery paramQuery
-        (m_urlString,
+        (SimpleSPARQLQuery::QueryFromModel,
          QString
          (
              " PREFIX vamp: <http://purl.org/ontology/vamp/> "
              
              " SELECT ?param_id ?param_value "
              
-             " FROM <%1> "
-             " FROM <%2> "
-             
              " WHERE { "
-             "   <%3> vamp:parameter_binding ?binding . "
+             "   <%1> vamp:parameter_binding ?binding . "
              "   ?binding vamp:parameter ?param ; "
              "            vamp:value ?param_value . "
              "   ?param vamp:identifier ?param_id "
              " } "
              )
-         .arg(m_urlString)
-         .arg(pluginDescriptionURL)
          .arg(transformUri));
     
     SimpleSPARQLQuery::ResultList paramResults = paramQuery.execute();