# HG changeset patch
# User Chris Cannam
# Date 1227283949 0
# Node ID 82ab61fa9223799dee1aff76962d7d5304426519
# Parent 1c66e199e7d9aea5943ef49586d11191764d0bcd
* 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!)
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/PluginRDFDescription.cpp
--- a/rdf/PluginRDFDescription.cpp Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/PluginRDFDescription.cpp Fri Nov 21 16:12:29 2008 +0000
@@ -34,15 +34,14 @@
m_haveDescription(false)
{
PluginRDFIndexer *indexer = PluginRDFIndexer::getInstance();
- QString url = indexer->getDescriptionURLForPluginId(pluginId);
- if (url == "") {
+ m_pluginUri = indexer->getURIForPluginId(pluginId);
+ if (m_pluginUri == "") {
cerr << "PluginRDFDescription: WARNING: No RDF description available for plugin ID \""
<< pluginId.toStdString() << "\"" << endl;
} else {
- if (!indexURL(url)) {
- cerr << "PluginRDFDescription: ERROR: Failed to query RDF description for plugin ID \""
- << pluginId.toStdString() << "\"" << endl;
- } else {
+ // All the data we need should be in our RDF model already:
+ // if it's not there, we don't know where to find it anyway
+ if (index()) {
m_haveDescription = true;
}
}
@@ -151,83 +150,63 @@
}
bool
-PluginRDFDescription::indexURL(QString url)
+PluginRDFDescription::index()
{
- Profiler profiler("PluginRDFDescription::indexURL");
-
- QString type, soname, label;
- PluginIdentifier::parseIdentifier(m_pluginId, type, soname, label);
+ Profiler profiler("PluginRDFDescription::index");
bool success = true;
-
- QString local = url;
-
- if (FileSource::isRemote(url) &&
- FileSource::canHandleScheme(url)) {
-
- CachedFile cf(url);
- if (!cf.isOK()) {
- return false;
- }
-
- local = QUrl::fromLocalFile(cf.getLocalFilename()).toString();
- }
-
- if (!indexMetadata(local, label)) success = false;
- if (!indexOutputs(local, label)) success = false;
+ if (!indexMetadata()) success = false;
+ if (!indexOutputs()) success = false;
return success;
}
bool
-PluginRDFDescription::indexMetadata(QString url, QString label)
+PluginRDFDescription::indexMetadata()
{
- Profiler profiler("PluginRDFDescription::indexMetadata");
+ Profiler profiler("PluginRDFDescription::index");
+
+ SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
QString queryTemplate =
QString(
" PREFIX vamp: "
" PREFIX foaf: "
" PREFIX dc: "
- " SELECT ?%4 FROM <%1> "
+ " SELECT ?%3 "
" WHERE { "
- " ?plugin vamp:identifier \"%2\" ; "
- " a vamp:Plugin ; "
- " %3 ?%4 . "
+ " <%1> %2 ?%3 . "
" }")
- .arg(url)
- .arg(label);
+ .arg(m_pluginUri);
SimpleSPARQLQuery::Value v;
v = SimpleSPARQLQuery::singleResultQuery
- (url, queryTemplate.arg("vamp:name").arg("name"), "name");
+ (m, queryTemplate.arg("vamp:name").arg("name"), "name");
if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
m_pluginName = v.value;
}
v = SimpleSPARQLQuery::singleResultQuery
- (url, queryTemplate.arg("dc:description").arg("description"), "description");
+ (m, queryTemplate.arg("dc:description").arg("description"), "description");
if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
m_pluginDescription = v.value;
}
v = SimpleSPARQLQuery::singleResultQuery
- (url,
+ (m,
QString(
" PREFIX vamp: "
" PREFIX foaf: "
- " SELECT ?name FROM <%1> "
+ " SELECT ?name "
" WHERE { "
- " ?plugin vamp:identifier \"%2\" ; "
- " a vamp:Plugin ; "
- " foaf:maker ?maker . "
+ " <%1> foaf:maker ?maker . "
" ?maker foaf:name ?name . "
" }")
- .arg(url)
- .arg(label), "name");
+ .arg(m_pluginUri),
+ "name");
if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
m_pluginMaker = v.value;
@@ -240,18 +219,16 @@
// perhaps that would be unwise
v = SimpleSPARQLQuery::singleResultQuery
- (url,
+ (m,
QString(
" PREFIX vamp: "
" PREFIX foaf: "
- " SELECT ?page from <%1> "
+ " SELECT ?page "
" WHERE { "
- " ?plugin vamp:identifier \"%2\" ; "
- " a vamp:Plugin ; "
- " foaf:page ?page . "
+ " <%1> foaf:page ?page . "
" }")
- .arg(url)
- .arg(label), "page");
+ .arg(m_pluginUri),
+ "page");
if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
@@ -260,20 +237,18 @@
} else {
v = SimpleSPARQLQuery::singleResultQuery
- (url,
+ (m,
QString(
" PREFIX vamp: "
" PREFIX foaf: "
- " SELECT ?page from <%1> "
+ " SELECT ?page "
" WHERE { "
- " ?library a vamp:PluginLibrary ; "
- " vamp:available_plugin ?plugin ; "
+ " ?library vamp:available_plugin <%1> ; "
+ " a vamp:PluginLibrary ; "
" foaf:page ?page . "
- " ?plugin a vamp:Plugin ; "
- " vamp:identifier \"%2\" . "
" }")
- .arg(url)
- .arg(label), "page");
+ .arg(m_pluginUri),
+ "page");
if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
@@ -285,24 +260,23 @@
}
bool
-PluginRDFDescription::indexOutputs(QString url, QString label)
+PluginRDFDescription::indexOutputs()
{
Profiler profiler("PluginRDFDescription::indexOutputs");
+
+ SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
SimpleSPARQLQuery query
- (url,
+ (m,
QString
(
" PREFIX vamp: "
" SELECT ?output ?output_id ?output_type ?unit "
- " FROM <%1> "
" WHERE { "
- " ?plugin vamp:identifier \"%2\" ; "
- " a vamp:Plugin ; "
- " vamp:output ?output . "
+ " <%1> vamp:output ?output . "
" ?output vamp:identifier ?output_id ; "
" a ?output_type . "
@@ -313,23 +287,20 @@
" } "
)
- .arg(url)
- .arg(label));
+ .arg(m_pluginUri));
SimpleSPARQLQuery::ResultList results = query.execute();
if (!query.isOK()) {
- cerr << "ERROR: PluginRDFDescription::indexURL: ERROR: Failed to query document at <"
- << url.toStdString() << ">: "
+ cerr << "ERROR: PluginRDFDescription::index: ERROR: Failed to query outputs for <"
+ << m_pluginUri.toStdString() << ">: "
<< query.getErrorString().toStdString() << endl;
return false;
}
if (results.empty()) {
- cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: Document at <"
- << url.toStdString()
- << "> does not appear to describe any outputs for plugin with id \""
- << label.toStdString() << "\"" << endl;
+ cerr << "ERROR: PluginRDFDescription::indexURL: NOTE: No outputs defined for <"
+ << m_pluginUri.toStdString() << ">" << endl;
return false;
}
@@ -365,12 +336,12 @@
SimpleSPARQLQuery::Value v;
v = SimpleSPARQLQuery::singleResultQuery
- (url,
+ (m,
QString(" PREFIX vamp: "
" PREFIX dc: "
- " SELECT ?title FROM <%1> "
+ " SELECT ?title "
" WHERE { <%2> dc:title ?title } ")
- .arg(url).arg(outputUri), "title");
+ .arg(outputUri), "title");
if (v.type == SimpleSPARQLQuery::LiteralValue && v.value != "") {
m_outputNames[outputId] = v.value;
@@ -378,26 +349,26 @@
QString queryTemplate =
QString(" PREFIX vamp: "
- " SELECT ?%3 FROM <%1> "
+ " SELECT ?%3 "
" WHERE { <%2> vamp:computes_%3 ?%3 } ")
- .arg(url).arg(outputUri);
+ .arg(outputUri);
v = SimpleSPARQLQuery::singleResultQuery
- (url, queryTemplate.arg("event_type"), "event_type");
+ (m, queryTemplate.arg("event_type"), "event_type");
if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
m_outputEventTypeURIMap[outputId] = v.value;
}
v = SimpleSPARQLQuery::singleResultQuery
- (url, queryTemplate.arg("feature_attribute"), "feature_attribute");
+ (m, queryTemplate.arg("feature_attribute"), "feature_attribute");
if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
m_outputFeatureAttributeURIMap[outputId] = v.value;
}
v = SimpleSPARQLQuery::singleResultQuery
- (url, queryTemplate.arg("signal_type"), "signal_type");
+ (m, queryTemplate.arg("signal_type"), "signal_type");
if (v.type == SimpleSPARQLQuery::URIValue && v.value != "") {
m_outputSignalTypeURIMap[outputId] = v.value;
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/PluginRDFDescription.h
--- a/rdf/PluginRDFDescription.h Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/PluginRDFDescription.h Fri Nov 21 16:12:29 2008 +0000
@@ -55,6 +55,7 @@
typedef std::map OutputStringMap;
QString m_pluginId;
+ QString m_pluginUri;
bool m_haveDescription;
QString m_pluginName;
QString m_pluginDescription;
@@ -66,9 +67,9 @@
OutputStringMap m_outputFeatureAttributeURIMap;
OutputStringMap m_outputSignalTypeURIMap;
OutputStringMap m_outputUnitMap;
- bool indexURL(QString url);
- bool indexMetadata(QString url, QString label);
- bool indexOutputs(QString url, QString label);
+ bool index();
+ bool indexMetadata();
+ bool indexOutputs();
};
#endif
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/PluginRDFIndexer.cpp
--- a/rdf/PluginRDFIndexer.cpp Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/PluginRDFIndexer.cpp Fri Nov 21 16:12:29 2008 +0000
@@ -87,7 +87,7 @@
for (QStringList::const_iterator j = entries.begin();
j != entries.end(); ++j) {
QFileInfo fi(dir.filePath(*j));
- indexFile(fi.absoluteFilePath());
+ pullFile(fi.absoluteFilePath());
}
QStringList subdirs = dir.entryList
@@ -102,11 +102,13 @@
for (QStringList::const_iterator k = entries.begin();
k != entries.end(); ++k) {
QFileInfo fi(subdir.filePath(*k));
- indexFile(fi.absoluteFilePath());
+ pullFile(fi.absoluteFilePath());
}
}
}
}
+
+ reindex();
}
bool
@@ -140,7 +142,7 @@
j != list.end(); ++j) {
std::cerr << "PluginRDFIndexer::indexConfiguredURLs: url is "
<< j->toStdString() << std::endl;
- indexURL(*j);
+ pullURL(*j);
}
}
@@ -148,10 +150,11 @@
QStringList urls = settings.value(urlListKey).toStringList();
for (int i = 0; i < urls.size(); ++i) {
- indexURL(urls[i]);
+ pullURL(urls[i]);
}
settings.endGroup();
+ reindex();
return true;
}
@@ -198,49 +201,39 @@
return id;
}
-QString
-PluginRDFIndexer::getDescriptionURLForPluginId(QString pluginId)
-{
- QMutexLocker locker(&m_mutex);
-
- if (m_idToDescriptionMap.find(pluginId) == m_idToDescriptionMap.end()) return "";
- return m_idToDescriptionMap[pluginId];
-}
-
-QString
-PluginRDFIndexer::getDescriptionURLForPluginURI(QString uri)
-{
- QMutexLocker locker(&m_mutex);
-
- QString id = getIdForPluginURI(uri);
- if (id == "") return "";
- return getDescriptionURLForPluginId(id);
-}
-
QStringList
PluginRDFIndexer::getIndexedPluginIds()
{
QMutexLocker locker(&m_mutex);
QStringList ids;
- for (StringMap::const_iterator i = m_idToDescriptionMap.begin();
- i != m_idToDescriptionMap.end(); ++i) {
+ for (StringMap::const_iterator i = m_idToUriMap.begin();
+ i != m_idToUriMap.end(); ++i) {
ids.push_back(i->first);
}
return ids;
}
bool
-PluginRDFIndexer::indexFile(QString filepath)
+PluginRDFIndexer::pullFile(QString filepath)
{
QUrl url = QUrl::fromLocalFile(filepath);
QString urlString = url.toString();
- return indexURL(urlString);
+ return pullURL(urlString);
}
bool
PluginRDFIndexer::indexURL(QString urlString)
{
+ bool pulled = pullURL(urlString);
+ if (!pulled) return false;
+ reindex();
+ return true;
+}
+
+bool
+PluginRDFIndexer::pullURL(QString urlString)
+{
Profiler profiler("PluginRDFIndexer::indexURL");
std::cerr << "PluginRDFIndexer::indexURL(" << urlString.toStdString() << ")" << std::endl;
@@ -258,51 +251,23 @@
}
localString = QUrl::fromLocalFile(cf.getLocalFilename()).toString();
-// localString = "file://" + cf.getLocalFilename(); //!!! crud - fix!
}
-// cerr << "PluginRDFIndexer::indexURL: url = <" << urlString.toStdString() << ">" << endl;
-/*!!!
+ return SimpleSPARQLQuery::addSourceToModel(localString);
+}
+
+bool
+PluginRDFIndexer::reindex()
+{
+ SimpleSPARQLQuery::QueryType m = SimpleSPARQLQuery::QueryFromModel;
+
SimpleSPARQLQuery query
- (localString,
- QString
- (
- " PREFIX vamp: "
-
- " SELECT ?plugin ?library_id ?plugin_id "
- " FROM <%1> "
-
- " WHERE { "
- " ?plugin a vamp:Plugin . "
-
- // Make the identifier and library parts optional, so
- // that we can check and report helpfully if one or both
- // is absent instead of just getting no results
-
- //!!! No -- because of rasqal's inability to correctly
- // handle more than one OPTIONAL graph in a query, let's
- // make identifier compulsory after all
- //" OPTIONAL { ?plugin vamp:identifier ?plugin_id } . "
-
- " ?plugin vamp:identifier ?plugin_id . "
-
- " OPTIONAL { "
- " ?library a vamp:PluginLibrary ; "
- " vamp:available_plugin ?plugin ; "
- " vamp:identifier ?library_id "
- " } "
- " } "
- )
- .arg(localString));
-*/
- SimpleSPARQLQuery query
- (localString,
+ (m,
QString
(
" PREFIX vamp: "
" SELECT ?plugin ?library ?plugin_id "
- " FROM <%1> "
" WHERE { "
" ?plugin a vamp:Plugin . "
@@ -312,22 +277,18 @@
" ?library vamp:available_plugin ?plugin "
" } "
" } "
- )
- .arg(localString));
+ ));
SimpleSPARQLQuery::ResultList results = query.execute();
if (!query.isOK()) {
- cerr << "ERROR: PluginRDFIndexer::indexURL: ERROR: Failed to index document at <"
- << urlString.toStdString() << ">: "
+ cerr << "ERROR: PluginRDFIndexer::reindex: ERROR: Failed to query plugins from model: "
<< query.getErrorString().toStdString() << endl;
return false;
}
if (results.empty()) {
- cerr << "PluginRDFIndexer::indexURL: NOTE: Document at <"
- << urlString.toStdString()
- << "> does not describe any vamp:Plugin resources" << endl;
+ cerr << "PluginRDFIndexer::reindex: NOTE: no vamp:Plugin resources found in indexed documents" << endl;
return false;
}
@@ -338,18 +299,17 @@
i != results.end(); ++i) {
QString pluginUri = (*i)["plugin"].value;
-//!!! QString soname = (*i)["library_id"].value;
QString soUri = (*i)["library"].value;
QString identifier = (*i)["plugin_id"].value;
if (identifier == "") {
- cerr << "PluginRDFIndexer::indexURL: NOTE: No vamp:identifier for plugin <"
+ cerr << "PluginRDFIndexer::reindex: NOTE: No vamp:identifier for plugin <"
<< pluginUri.toStdString() << ">"
<< endl;
continue;
}
if (soUri == "") {
- cerr << "PluginRDFIndexer::indexURL: NOTE: No implementation library for plugin <"
+ cerr << "PluginRDFIndexer::reindex: NOTE: No implementation library for plugin <"
<< pluginUri.toStdString() << ">"
<< endl;
continue;
@@ -359,69 +319,40 @@
QString(
" PREFIX vamp: "
" SELECT ?library_id "
- " FROM <%1> "
" WHERE { "
- " <%2> vamp:identifier ?library_id "
+ " <%1> vamp:identifier ?library_id "
" } "
)
- .arg(localString)
.arg(soUri);
SimpleSPARQLQuery::Value sonameValue =
- SimpleSPARQLQuery::singleResultQuery(localString, sonameQuery, "library_id");
+ SimpleSPARQLQuery::singleResultQuery(m, sonameQuery, "library_id");
QString soname = sonameValue.value;
if (soname == "") {
- cerr << "PluginRDFIndexer::indexURL: NOTE: No identifier for library <"
+ cerr << "PluginRDFIndexer::reindex: NOTE: No identifier for library <"
<< soUri.toStdString() << ">"
<< endl;
continue;
}
-
-/*
- cerr << "PluginRDFIndexer::indexURL: Document for plugin \""
- << soname.toStdString() << ":" << identifier.toStdString()
- << "\" (uri <" << pluginUri.toStdString() << ">) is at url <"
- << urlString.toStdString() << ">" << endl;
-*/
QString pluginId = PluginIdentifier::createIdentifier
("vamp", soname, identifier);
foundSomething = true;
- if (m_idToDescriptionMap.find(pluginId) != m_idToDescriptionMap.end()) {
-/*!!!
-
- This can happen quite legitimately when using an RDF datastore rather
- than querying individual files, as of course the datastore contains
- all plugin data found so far, and each time a file is added to it,
- subsequent queries will return all older plugins as well.
-
- It would be more efficient to add everything at once and then do all
- queries, of course.
-
- cerr << "PluginRDFIndexer::indexURL: NOTE: Plugin id \""
- << pluginId.toStdString() << "\", described in document at <"
- << urlString.toStdString()
- << ">, has already been described in document <"
- << m_idToDescriptionMap[pluginId].toStdString()
- << ">: ignoring this new description" << endl;
-*/
+ if (m_idToUriMap.find(pluginId) != m_idToUriMap.end()) {
continue;
}
- m_idToDescriptionMap[pluginId] = urlString;
m_idToUriMap[pluginId] = pluginUri;
addedSomething = true;
if (pluginUri != "") {
if (m_uriToIdMap.find(pluginUri) != m_uriToIdMap.end()) {
- cerr << "PluginRDFIndexer::indexURL: WARNING: Found multiple plugins with the same URI:" << endl;
+ cerr << "PluginRDFIndexer::reindex: WARNING: Found multiple plugins with the same URI:" << endl;
cerr << " 1. Plugin id \"" << m_uriToIdMap[pluginUri].toStdString() << "\"" << endl;
- cerr << " described in <" << m_idToDescriptionMap[m_uriToIdMap[pluginUri]].toStdString() << ">" << endl;
cerr << " 2. Plugin id \"" << pluginId.toStdString() << "\"" << endl;
- cerr << " described in <" << urlString.toStdString() << ">" << endl;
cerr << "both claim URI <" << pluginUri.toStdString() << ">" << endl;
} else {
m_uriToIdMap[pluginUri] = pluginId;
@@ -430,9 +361,7 @@
}
if (!foundSomething) {
- cerr << "PluginRDFIndexer::indexURL: NOTE: Document at <"
- << urlString.toStdString()
- << "> does not sufficiently describe any plugins" << endl;
+ cerr << "PluginRDFIndexer::reindex: NOTE: Plugins found, but none sufficiently described" << endl;
}
return addedSomething;
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/PluginRDFIndexer.h
--- a/rdf/PluginRDFIndexer.h Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/PluginRDFIndexer.h Fri Nov 21 16:12:29 2008 +0000
@@ -45,8 +45,6 @@
QString getURIForPluginId(QString pluginId);
QString getIdForPluginURI(QString uri);
- QString getDescriptionURLForPluginId(QString pluginId);
- QString getDescriptionURLForPluginURI(QString uri);
QStringList getIndexedPluginIds();
@@ -59,10 +57,13 @@
typedef std::map StringMap;
StringMap m_uriToIdMap;
StringMap m_idToUriMap;
- StringMap m_idToDescriptionMap;
void indexInstalledURLs();
- bool indexFile(QString path);
+
+ bool pullFile(QString path);
+ bool pullURL(QString urlString);
+ bool reindex();
+
static PluginRDFIndexer *m_instance;
};
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/RDFImporter.cpp
--- a/rdf/RDFImporter.cpp Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/RDFImporter.cpp Fri Nov 21 16:12:29 2008 +0000
@@ -142,7 +142,7 @@
ProgressReporter *reporter)
{
SimpleSPARQLQuery query = SimpleSPARQLQuery
- (m_uristring,
+ (SimpleSPARQLQuery::QueryFromSingleSource,
QString
(
" PREFIX mo: "
@@ -258,6 +258,8 @@
int &sampleRate, int &windowLength,
int &hopSize, int &width, int &height)
{
+ SimpleSPARQLQuery::QueryType s = SimpleSPARQLQuery::QueryFromSingleSource;
+
QString dimensionsQuery
(
" PREFIX mo: "
@@ -274,10 +276,8 @@
);
SimpleSPARQLQuery::Value dimensionsValue =
- SimpleSPARQLQuery::singleResultQuery(m_uristring,
- dimensionsQuery
- .arg(m_uristring).arg(featureUri),
- "dimensions");
+ SimpleSPARQLQuery::singleResultQuery
+ (s, dimensionsQuery.arg(m_uristring).arg(featureUri), "dimensions");
cerr << "Dimensions = \"" << dimensionsValue.value.toStdString() << "\""
<< endl;
@@ -316,7 +316,7 @@
// multiple optionals properly
SimpleSPARQLQuery::Value srValue =
- SimpleSPARQLQuery::singleResultQuery(m_uristring,
+ SimpleSPARQLQuery::singleResultQuery(s,
queryTemplate
.arg(m_uristring).arg(featureUri)
.arg("sampleRate"),
@@ -326,7 +326,7 @@
}
SimpleSPARQLQuery::Value hopValue =
- SimpleSPARQLQuery::singleResultQuery(m_uristring,
+ SimpleSPARQLQuery::singleResultQuery(s,
queryTemplate
.arg(m_uristring).arg(featureUri)
.arg("hopSize"),
@@ -336,7 +336,7 @@
}
SimpleSPARQLQuery::Value winValue =
- SimpleSPARQLQuery::singleResultQuery(m_uristring,
+ SimpleSPARQLQuery::singleResultQuery(s,
queryTemplate
.arg(m_uristring).arg(featureUri)
.arg("windowLength"),
@@ -352,6 +352,8 @@
RDFImporterImpl::getDataModelsSparse(std::vector &models,
ProgressReporter *reporter)
{
+ SimpleSPARQLQuery::QueryType s = SimpleSPARQLQuery::QueryFromSingleSource;
+
// Our query is intended to retrieve every thing that has a time,
// and every feature type and value associated with a thing that
// has a time.
@@ -443,7 +445,7 @@
).arg(m_uristring);
- SimpleSPARQLQuery query(m_uristring, queryString);
+ SimpleSPARQLQuery query(s, queryString);
query.setProgressReporter(reporter);
cerr << "Query will be: " << queryString.toStdString() << endl;
@@ -505,9 +507,9 @@
bool haveDuration = false;
QString label = SimpleSPARQLQuery::singleResultQuery
- (m_uristring, labelQueryString.arg(thinguri), "label").value;
+ (s, labelQueryString.arg(thinguri), "label").value;
- SimpleSPARQLQuery rangeQuery(m_uristring, rangeQueryString.arg(thinguri));
+ SimpleSPARQLQuery rangeQuery(s, rangeQueryString.arg(thinguri));
SimpleSPARQLQuery::ResultList rangeResults = rangeQuery.execute();
if (!rangeResults.empty()) {
// std::cerr << rangeResults.size() << " range results" << std::endl;
@@ -520,7 +522,7 @@
haveDuration = true;
} else {
QString timestring = SimpleSPARQLQuery::singleResultQuery
- (m_uristring, timeQueryString.arg(thinguri), "time").value;
+ (s, timeQueryString.arg(thinguri), "time").value;
if (timestring != "") {
time = RealTime::fromXsdDuration(timestring.toStdString());
haveTime = true;
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/RDFTransformFactory.cpp
--- 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 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 uriTransformMap;
- QString queryTemplate =
+ QString query =
" PREFIX 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: "
+
+ " 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::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: "
+
+ " 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: "
" 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: "
" 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();
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/SimpleSPARQLQuery.cpp
--- a/rdf/SimpleSPARQLQuery.cpp Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/SimpleSPARQLQuery.cpp Fri Nov 21 16:12:29 2008 +0000
@@ -29,9 +29,7 @@
#include
#endif
-#ifdef HAVE_REDLAND
#include
-#endif
//#define DEBUG_SIMPLE_SPARQL_QUERY 1
@@ -64,6 +62,8 @@
rasqal_free_world(m_world);
}
+ bool isOK() const { return (m_world != 0); }
+
rasqal_world *getWorld() { return m_world; }
const rasqal_world *getWorld() const { return m_world; }
@@ -72,7 +72,6 @@
};
#endif
-#ifdef HAVE_REDLAND
class WredlandWorldWrapper
{
public:
@@ -169,14 +168,15 @@
QMutex m_mutex;
std::map m_parsedUris;
};
-#endif
class SimpleSPARQLQuery::Impl
{
public:
- Impl(QString fromUri, QString query);
+ Impl(SimpleSPARQLQuery::QueryType, QString query);
~Impl();
+ static bool addSourceToModel(QString sourceUri);
+
void setProgressReporter(ProgressReporter *reporter) { m_reporter = reporter; }
bool wasCancelled() const { return m_cancelled; }
@@ -185,10 +185,6 @@
bool isOK() const;
QString getErrorString() const;
- static void setBackEnd(SimpleSPARQLQuery::BackEndPreference p) {
- m_preference = p;
- }
-
protected:
static void errorHandler(void *, raptor_locator *, const char *);
@@ -200,16 +196,12 @@
static bool m_rasqalInitialised;
#endif
-#ifdef HAVE_REDLAND
static WredlandWorldWrapper *m_redland;
-#endif
-
- static SimpleSPARQLQuery::BackEndPreference m_preference;
ResultList executeDirectParser();
ResultList executeDatastore();
- QString m_fromUri;
+ QueryType m_type;
QString m_query;
QString m_errorString;
ProgressReporter *m_reporter;
@@ -222,17 +214,12 @@
bool SimpleSPARQLQuery::Impl::m_rasqalInitialised = false;
#endif
-#ifdef HAVE_REDLAND
WredlandWorldWrapper *SimpleSPARQLQuery::Impl::m_redland = 0;
-#endif
QMutex SimpleSPARQLQuery::Impl::m_mutex;
-SimpleSPARQLQuery::BackEndPreference
-SimpleSPARQLQuery::Impl::m_preference = SimpleSPARQLQuery::AutoSelectBackEnd;
-
-SimpleSPARQLQuery::SimpleSPARQLQuery(QString fromUri, QString query) :
- m_impl(new Impl(fromUri, query))
+SimpleSPARQLQuery::SimpleSPARQLQuery(QueryType type, QString query) :
+ m_impl(new Impl(type, query))
{
}
@@ -271,14 +258,14 @@
return m_impl->getErrorString();
}
-void
-SimpleSPARQLQuery::setBackEnd(BackEndPreference p)
+bool
+SimpleSPARQLQuery::addSourceToModel(QString sourceUri)
{
- SimpleSPARQLQuery::Impl::setBackEnd(p);
+ return SimpleSPARQLQuery::Impl::addSourceToModel(sourceUri);
}
-SimpleSPARQLQuery::Impl::Impl(QString fromUri, QString query) :
- m_fromUri(fromUri),
+SimpleSPARQLQuery::Impl::Impl(QueryType type, QString query) :
+ m_type(type),
m_query(query),
m_reporter(0),
m_cancelled(false)
@@ -328,48 +315,32 @@
{
ResultList list;
- BackEndPreference preference;
-
m_mutex.lock();
- if (m_preference == AutoSelectBackEnd) {
-#ifdef HAVE_REDLAND
-// cerr << "librdf version: " << librdf_version_major << "." << librdf_version_minor << "." << librdf_version_release << endl;
- if (librdf_version_major > 1 ||
- (librdf_version_major == 1 &&
- (librdf_version_minor > 0 ||
- (librdf_version_minor == 0 &&
- librdf_version_release > 7)))) {
- cerr << "SimpleSPARQLQuery: Auto-selecting LIBRDF back-end for tree-based storage" << endl;
- m_preference = DatastoreBackEnd;
- }
-#endif
- if (m_preference == AutoSelectBackEnd) {
- cerr << "SimpleSPARQLQuery: Auto-selecting RASQAL back-end" << endl;
- m_preference = DirectParserBackEnd;
+ if (m_type == QueryFromModel) {
+ if (!m_redland) {
+ // There can be no results, because no sources have been
+ // added to the model yet (m_redland is only created when
+ // addSourceToModel is called)
+ cerr << "SimpleSPARQLQuery::execute: NOTE: No sources have been added to data model yet, so no results are possible" << endl;
+ m_mutex.unlock();
+ return list;
}
}
- if (m_preference == DatastoreBackEnd) {
-#ifdef HAVE_REDLAND
- if (!m_redland) {
- m_redland = new WredlandWorldWrapper();
- if (!m_redland->isOK()) {
- cerr << "WARNING: SimpleSPARQLQuery::execute: Failed to initialise Redland datastore, falling back to direct parser implementation" << endl;
- delete m_redland;
- m_preference = DirectParserBackEnd;
+ if (m_type == QueryFromSingleSource) {
+#ifdef USE_NEW_RASQAL_API
+ if (!m_rasqal) {
+ m_rasqal = new WrasqalWorldWrapper();
+ if (!m_rasqal->isOK()) {
+ cerr << "ERROR: SimpleSPARQLQuery::execute: Failed to initialise Rasqal query engine" << endl;
+ delete m_rasqal;
+ m_rasqal = 0;
+ m_mutex.unlock();
+ return list;
}
}
#else
- cerr << "WARNING: SimpleSPARQLQuery::execute: Datastore implementation preference indicated, but no datastore compiled in; using direct parser" << endl;
- m_preference = DirectParserBackEnd;
-#endif
- }
-
- if (m_preference == DirectParserBackEnd) {
-#ifdef USE_NEW_RASQAL_API
- if (!m_rasqal) m_rasqal = new WrasqalWorldWrapper();
-#else
if (!m_rasqalInitialised) {
rasqal_init();
m_rasqalInitialised = true;
@@ -377,10 +348,9 @@
#endif
}
- preference = m_preference;
m_mutex.unlock();
- if (preference == SimpleSPARQLQuery::DirectParserBackEnd) {
+ if (m_type == QueryFromSingleSource) {
return executeDirectParser();
} else {
return executeDatastore();
@@ -510,19 +480,9 @@
SimpleSPARQLQuery::Impl::executeDatastore()
{
ResultList list;
-#ifndef HAVE_REDLAND
- // This should have been caught by execute()
- cerr << "SimpleSPARQLQuery: INTERNAL ERROR: Datastore not compiled in" << endl;
- return list;
-#else
+
Profiler profiler("SimpleSPARQLQuery::executeDatastore");
- librdf_uri *uri = m_redland->getUri(m_fromUri, m_errorString);
- if (!uri) return list;
-
-#ifdef DEBUG_SIMPLE_SPARQL_QUERY
- std::cerr << "SimpleSPARQLQuery: Query is: \"" << m_query.toStdString() << "\"" << std::endl;
-#endif
/*!!!
static std::map counter;
if (counter.find(m_query) == counter.end()) counter[m_query] = 1;
@@ -537,7 +497,7 @@
Profiler p("SimpleSPARQLQuery: Prepare LIBRDF query");
query = librdf_new_query
(m_redland->getWorld(), "sparql", NULL,
- (const unsigned char *)m_query.toUtf8().data(), uri);
+ (const unsigned char *)m_query.toUtf8().data(), NULL);
}
if (!query) {
@@ -650,14 +610,42 @@
#endif
return list;
-#endif
+}
+
+bool
+SimpleSPARQLQuery::Impl::addSourceToModel(QString sourceUri)
+{
+ QString err;
+
+ m_mutex.lock();
+
+ if (!m_redland) {
+ m_redland = new WredlandWorldWrapper();
+ if (!m_redland->isOK()) {
+ cerr << "ERROR: SimpleSPARQLQuery::addSourceToModel: Failed to initialise Redland datastore" << endl;
+ delete m_redland;
+ m_redland = 0;
+ m_mutex.unlock();
+ return false;
+ }
+ }
+
+ m_mutex.unlock();
+
+ librdf_uri *uri = m_redland->getUri(sourceUri, err);
+
+ if (!uri) {
+ std::cerr << "SimpleSPARQLQuery::addSourceToModel: Failed to add source URI \"" << sourceUri.toStdString() << ": " << err.toStdString() << std::endl;
+ return false;
+ }
+ return true;
}
SimpleSPARQLQuery::Value
-SimpleSPARQLQuery::singleResultQuery(QString fromUri,
+SimpleSPARQLQuery::singleResultQuery(QueryType type,
QString query, QString binding)
{
- SimpleSPARQLQuery q(fromUri, query);
+ SimpleSPARQLQuery q(type, query);
ResultList results = q.execute();
if (!q.isOK()) {
cerr << "SimpleSPARQLQuery::singleResultQuery: ERROR: "
diff -r 1c66e199e7d9 -r 82ab61fa9223 rdf/SimpleSPARQLQuery.h
--- a/rdf/SimpleSPARQLQuery.h Fri Nov 21 14:25:33 2008 +0000
+++ b/rdf/SimpleSPARQLQuery.h Fri Nov 21 16:12:29 2008 +0000
@@ -37,9 +37,16 @@
typedef std::map KeyValueMap;
typedef std::vector ResultList;
- SimpleSPARQLQuery(QString fromUri, QString query);
+ enum QueryType {
+ QueryFromModel,
+ QueryFromSingleSource
+ };
+
+ SimpleSPARQLQuery(QueryType type, QString query);
~SimpleSPARQLQuery();
+ static bool addSourceToModel(QString sourceUri);
+
void setProgressReporter(ProgressReporter *reporter);
bool wasCancelled() const;
@@ -50,21 +57,10 @@
// Do a query and return the value for the given binding, from the
// first result that has a value for it
- static Value singleResultQuery(QString fromUri,
+ static Value singleResultQuery(QueryType type,
QString query,
QString binding);
- enum BackEndPreference {
- AutoSelectBackEnd, // pick based on likely speed of available storage
- DirectParserBackEnd, // use rasqal (simpler if seldom used)
- DatastoreBackEnd, // use redland (faster if version not too old)
- };
- /**
- * Select the preferred query back end. This should be called
- * before any queries are made. The default is AutoSelectBackEnd.
- */
- static void setBackEnd(BackEndPreference);
-
protected:
class Impl;
Impl *m_impl;
diff -r 1c66e199e7d9 -r 82ab61fa9223 transform/TransformFactory.cpp
--- a/transform/TransformFactory.cpp Fri Nov 21 14:25:33 2008 +0000
+++ b/transform/TransformFactory.cpp Fri Nov 21 16:12:29 2008 +0000
@@ -295,6 +295,7 @@
case TransformDescription::Generator: return tr("Generator");
case TransformDescription::UnknownType: return tr("Other");
}
+ return tr("Other");
}
void