comparison rdf/PluginRDFIndexer.cpp @ 439:beb2948baa77

* Merge revisions 1041 to 1130 from sv-rdf-import branch
author Chris Cannam
date Thu, 18 Sep 2008 12:09:32 +0000
parents
children 5746c559af15
comparison
equal deleted inserted replaced
438:32c399d06374 439:beb2948baa77
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2008 QMUL.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "PluginRDFIndexer.h"
17
18 #include "SimpleSPARQLQuery.h"
19
20 #include "data/fileio/FileSource.h"
21 #include "plugin/PluginIdentifier.h"
22
23 #include <vamp-sdk/PluginHostAdapter.h>
24
25 #include <QFileInfo>
26 #include <QDir>
27 #include <QUrl>
28
29 #include <iostream>
30 using std::cerr;
31 using std::endl;
32 using std::vector;
33 using std::string;
34 using Vamp::PluginHostAdapter;
35
36 PluginRDFIndexer *
37 PluginRDFIndexer::m_instance = 0;
38
39 PluginRDFIndexer *
40 PluginRDFIndexer::getInstance()
41 {
42 if (!m_instance) m_instance = new PluginRDFIndexer();
43 return m_instance;
44 }
45
46 PluginRDFIndexer::PluginRDFIndexer()
47 {
48 vector<string> paths = PluginHostAdapter::getPluginPath();
49
50 QStringList filters;
51 filters << "*.n3";
52 filters << "*.N3";
53 filters << "*.rdf";
54 filters << "*.RDF";
55
56 // Search each Vamp plugin path for a .rdf file that either has
57 // name "soname", "soname:label" or "soname/label" plus RDF
58 // extension. Use that order of preference, and prefer n3 over
59 // rdf extension.
60
61 for (vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
62
63 QDir dir(i->c_str());
64 if (!dir.exists()) continue;
65
66 QStringList entries = dir.entryList
67 (filters, QDir::Files | QDir::Readable);
68
69 for (QStringList::const_iterator j = entries.begin();
70 j != entries.end(); ++j) {
71 QFileInfo fi(dir.filePath(*j));
72 indexFile(fi.absoluteFilePath());
73 }
74
75 QStringList subdirs = dir.entryList
76 (QDir::AllDirs | QDir::NoDotAndDotDot | QDir::Readable);
77
78 for (QStringList::const_iterator j = subdirs.begin();
79 j != subdirs.end(); ++j) {
80 QDir subdir(dir.filePath(*j));
81 if (subdir.exists()) {
82 entries = subdir.entryList
83 (filters, QDir::Files | QDir::Readable);
84 for (QStringList::const_iterator k = entries.begin();
85 k != entries.end(); ++k) {
86 QFileInfo fi(subdir.filePath(*k));
87 indexFile(fi.absoluteFilePath());
88 }
89 }
90 }
91 }
92 }
93
94 PluginRDFIndexer::~PluginRDFIndexer()
95 {
96 while (!m_cache.empty()) {
97 delete *m_cache.begin();
98 m_cache.erase(m_cache.begin());
99 }
100 }
101
102 QString
103 PluginRDFIndexer::getURIForPluginId(QString pluginId)
104 {
105 if (m_idToUriMap.find(pluginId) == m_idToUriMap.end()) return "";
106 return m_idToUriMap[pluginId];
107 }
108
109 QString
110 PluginRDFIndexer::getIdForPluginURI(QString uri)
111 {
112 if (m_uriToIdMap.find(uri) == m_uriToIdMap.end()) {
113
114 // Haven't found this uri referenced in any document on the
115 // local filesystem; try resolving the pre-fragment part of
116 // the uri as a document URL and reading that if possible.
117
118 // Because we may want to refer to this document again, we
119 // cache it locally if it turns out to exist.
120
121 cerr << "PluginRDFIndexer::getIdForPluginURI: NOTE: Failed to find a local RDF document describing plugin <" << uri.toStdString() << ">: attempting to retrieve one remotely by guesswork" << endl;
122
123 QString baseUrl = QUrl(uri).toString(QUrl::RemoveFragment);
124
125 FileSource source(baseUrl);
126 if (source.isAvailable()) {
127 source.waitForData();
128 if (indexFile(source.getLocalFilename())) {
129 m_cache.insert(new FileSource(source));
130 }
131 }
132
133 if (m_uriToIdMap.find(uri) == m_uriToIdMap.end()) {
134 m_uriToIdMap[uri] = "";
135 }
136 }
137
138 return m_uriToIdMap[uri];
139 }
140
141 QString
142 PluginRDFIndexer::getDescriptionURLForPluginId(QString pluginId)
143 {
144 if (m_idToDescriptionMap.find(pluginId) == m_idToDescriptionMap.end()) return "";
145 return m_idToDescriptionMap[pluginId];
146 }
147
148 QString
149 PluginRDFIndexer::getDescriptionURLForPluginURI(QString uri)
150 {
151 QString id = getIdForPluginURI(uri);
152 if (id == "") return "";
153 return getDescriptionURLForPluginId(id);
154 }
155
156 bool
157 PluginRDFIndexer::indexFile(QString filepath)
158 {
159 QUrl url = QUrl::fromLocalFile(filepath);
160 QString urlString = url.toString();
161 return indexURL(urlString);
162 }
163
164 bool
165 PluginRDFIndexer::indexURL(QString urlString)
166 {
167 // cerr << "PluginRDFIndexer::indexURL: url = <" << urlString.toStdString() << ">" << endl;
168
169 SimpleSPARQLQuery query
170 (QString
171 (
172 " PREFIX vamp: <http://purl.org/ontology/vamp/> "
173
174 " SELECT ?plugin ?library_id ?plugin_id "
175 " FROM <%1> "
176
177 " WHERE { "
178 " ?plugin a vamp:Plugin . "
179
180 // Make the identifier and library parts optional, so
181 // that we can check and report helpfully if one or both
182 // is absent instead of just getting no results
183
184 " OPTIONAL { ?plugin vamp:identifier ?plugin_id } . "
185
186 " OPTIONAL { "
187 " ?library a vamp:PluginLibrary ; "
188 " vamp:available_plugin ?plugin ; "
189 " vamp:identifier ?library_id "
190 " } "
191 " } "
192 )
193 .arg(urlString));
194
195 SimpleSPARQLQuery::ResultList results = query.execute();
196
197 if (!query.isOK()) {
198 cerr << "ERROR: PluginRDFIndexer::indexURL: ERROR: Failed to index document at <"
199 << urlString.toStdString() << ">: "
200 << query.getErrorString().toStdString() << endl;
201 return false;
202 }
203
204 if (results.empty()) {
205 cerr << "PluginRDFIndexer::indexURL: NOTE: Document at <"
206 << urlString.toStdString()
207 << "> does not describe any vamp:Plugin resources" << endl;
208 return false;
209 }
210
211 bool foundSomething = false;
212 bool addedSomething = false;
213
214 for (SimpleSPARQLQuery::ResultList::iterator i = results.begin();
215 i != results.end(); ++i) {
216
217 QString pluginUri = (*i)["plugin"].value;
218 QString soname = (*i)["library_id"].value;
219 QString identifier = (*i)["plugin_id"].value;
220
221 if (identifier == "") {
222 cerr << "PluginRDFIndexer::indexURL: NOTE: Document at <"
223 << urlString.toStdString()
224 << "> fails to define any vamp:identifier for plugin <"
225 << pluginUri.toStdString() << ">"
226 << endl;
227 continue;
228 }
229 if (soname == "") {
230 cerr << "PluginRDFIndexer::indexURL: NOTE: Document at <"
231 << urlString.toStdString() << "> does not associate plugin <"
232 << pluginUri.toStdString() << "> with any implementation library"
233 << endl;
234 continue;
235 }
236 /*
237 cerr << "PluginRDFIndexer::indexURL: Document for plugin \""
238 << soname.toStdString() << ":" << identifier.toStdString()
239 << "\" (uri <" << pluginUri.toStdString() << ">) is at url <"
240 << urlString.toStdString() << ">" << endl;
241 */
242 QString pluginId = PluginIdentifier::createIdentifier
243 ("vamp", soname, identifier);
244
245 foundSomething = true;
246
247 if (m_idToDescriptionMap.find(pluginId) != m_idToDescriptionMap.end()) {
248 cerr << "PluginRDFIndexer::indexURL: NOTE: Plugin id \""
249 << pluginId.toStdString() << "\", described in document at <"
250 << urlString.toStdString()
251 << ">, has already been described in document <"
252 << m_idToDescriptionMap[pluginId].toStdString()
253 << ">: ignoring this new description" << endl;
254 continue;
255 }
256
257 m_idToDescriptionMap[pluginId] = urlString;
258 m_idToUriMap[pluginId] = pluginUri;
259
260 addedSomething = true;
261
262 if (pluginUri != "") {
263 if (m_uriToIdMap.find(pluginUri) != m_uriToIdMap.end()) {
264 cerr << "PluginRDFIndexer::indexURL: WARNING: Found multiple plugins with the same URI:" << endl;
265 cerr << " 1. Plugin id \"" << m_uriToIdMap[pluginUri].toStdString() << "\"" << endl;
266 cerr << " described in <" << m_idToDescriptionMap[m_uriToIdMap[pluginUri]].toStdString() << ">" << endl;
267 cerr << " 2. Plugin id \"" << pluginId.toStdString() << "\"" << endl;
268 cerr << " described in <" << urlString.toStdString() << ">" << endl;
269 cerr << "both claim URI <" << pluginUri.toStdString() << ">" << endl;
270 } else {
271 m_uriToIdMap[pluginUri] = pluginId;
272 }
273 }
274 }
275
276 if (!foundSomething) {
277 cerr << "PluginRDFIndexer::indexURL: NOTE: Document at <"
278 << urlString.toStdString()
279 << "> does not sufficiently describe any plugins" << endl;
280 }
281
282 return addedSomething;
283 }
284
285
286