svcore  1.9
RDFTransformFactory.cpp
Go to the documentation of this file.
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-2012 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 "RDFTransformFactory.h"
17 
18 #include <map>
19 #include <vector>
20 
21 #include <QTextStream>
22 #include <QUrl>
23 
24 #include <iostream>
25 #include <cmath>
26 
27 #include "PluginRDFIndexer.h"
28 #include "PluginRDFDescription.h"
29 #include "base/ProgressReporter.h"
31 
33 
34 #include <dataquay/BasicStore.h>
35 #include <dataquay/PropertyObject.h>
36 
37 using Dataquay::Uri;
38 using Dataquay::Node;
39 using Dataquay::Nodes;
40 using Dataquay::Triple;
41 using Dataquay::Triples;
42 using Dataquay::BasicStore;
43 using Dataquay::PropertyObject;
44 
45 
47 {
48 public:
49  RDFTransformFactoryImpl(QString url);
50  virtual ~RDFTransformFactoryImpl();
51 
52  bool isRDF();
53  bool isOK();
54  QString getErrorString() const;
55 
56  std::vector<Transform> getTransforms(ProgressReporter *);
57 
58  static QString writeTransformToRDF(const Transform &, QString);
59 
60 protected:
61  BasicStore *m_store;
62  QString m_urlString;
63  QString m_errorString;
64  bool m_isRDF;
65  bool setOutput(Transform &, QString);
66  bool setParameters(Transform &, QString);
67 };
68 
69 
70 QString
72 {
73  return "*.rdf *.n3 *.ttl";
74 }
75 
77  m_d(new RDFTransformFactoryImpl(url))
78 {
79 }
80 
82 {
83  delete m_d;
84 }
85 
86 bool
88 {
89  return m_d->isRDF();
90 }
91 
92 bool
94 {
95  return m_d->isOK();
96 }
97 
98 QString
100 {
101  return m_d->getErrorString();
102 }
103 
104 std::vector<Transform>
106 {
107  return m_d->getTransforms(r);
108 }
109 
110 QString
112 {
114 }
115 
117  m_store(new BasicStore),
118  m_urlString(url),
119  m_isRDF(false)
120 {
122  m_store->addPrefix("vamp", Uri("http://purl.org/ontology/vamp/"));
123  try {
124  QUrl qurl;
125  if (url.startsWith("file:")) {
126  qurl = QUrl(url);
127  } else {
128  qurl = QUrl::fromLocalFile(url);
129  }
130  m_store->import(qurl, BasicStore::ImportIgnoreDuplicates);
131  m_isRDF = true;
132  } catch (...) { }
133 }
134 
136 {
137  delete m_store;
138 }
139 
140 bool
142 {
143  return m_isRDF;
144 }
145 
146 bool
148 {
149  return (m_errorString == "");
150 }
151 
152 QString
154 {
155  return m_errorString;
156 }
157 
158 std::vector<Transform>
160 {
161  std::vector<Transform> transforms;
162 
163  std::map<QString, Transform> uriTransformMap;
164 
165  Nodes tnodes = m_store->match
166  (Triple(Node(), Uri("a"), m_store->expand("vamp:Transform"))).subjects();
167 
169 
170  foreach (Node tnode, tnodes) {
171 
172  Node pnode = m_store->complete
173  (Triple(tnode, m_store->expand("vamp:plugin"), Node()));
174 
175  if (pnode == Node()) {
176  cerr << "RDFTransformFactory: WARNING: No vamp:plugin for "
177  << "vamp:Transform node " << tnode
178  << ", skipping this transform" << endl;
179  continue;
180  }
181 
182  QString transformUri = tnode.value;
183  QString pluginUri = pnode.value;
184 
185  QString pluginId = indexer->getIdForPluginURI(pluginUri);
186  if (pluginId == "") {
187  cerr << "RDFTransformFactory: WARNING: Unknown plugin <"
188  << pluginUri << "> for transform <"
189  << transformUri << ">, skipping this transform"
190  << endl;
191  continue;
192  }
193 
194  Transform transform;
195  transform.setPluginIdentifier(pluginId);
196 
197  if (!setOutput(transform, transformUri)) {
198  return transforms;
199  }
200 
201  if (!setParameters(transform, transformUri)) {
202  return transforms;
203  }
204 
205  uriTransformMap[transformUri] = transform;
206 
207  static const char *optionals[] = {
208  "program",
209  "summary_type",
210  "step_size",
211  "block_size",
212  "window_type",
213  "sample_rate",
214  "start",
215  "duration"
216  };
217 
218  for (int j = 0; j < int(sizeof(optionals)/sizeof(optionals[0])); ++j) {
219 
220  QString optional = optionals[j];
221 
222  Node onode = m_store->complete
223  (Triple(Uri(transformUri),
224  m_store->expand(QString("vamp:") + optional), Node()));
225 
226  if (onode.type != Node::Literal) continue;
227 
228  if (optional == "program") {
229  transform.setProgram(onode.value);
230  } else if (optional == "summary_type") {
231  transform.setSummaryType
232  (transform.stringToSummaryType(onode.value));
233  } else if (optional == "step_size") {
234  transform.setStepSize(onode.value.toUInt());
235  } else if (optional == "block_size") {
236  transform.setBlockSize(onode.value.toUInt());
237  } else if (optional == "window_type") {
238  transform.setWindowType
240  (onode.value.toLower().toStdString()));
241  } else if (optional == "sample_rate") {
242  transform.setSampleRate(onode.value.toFloat());
243  } else if (optional == "start") {
244  transform.setStartTime
245  (RealTime::fromXsdDuration(onode.value.toStdString()));
246  } else if (optional == "duration") {
247  transform.setDuration
248  (RealTime::fromXsdDuration(onode.value.toStdString()));
249  } else {
250  cerr << "RDFTransformFactory: ERROR: Inconsistent optionals lists (unexpected optional \"" << optional << "\"" << endl;
251  }
252  }
253 
254  cerr << "RDFTransformFactory: NOTE: Transform is: " << endl;
255  cerr << transform.toXmlString() << endl;
256 
257  transforms.push_back(transform);
258  }
259 
260  return transforms;
261 }
262 
263 bool
265  QString transformUri)
266 {
267  Node outputNode = m_store->complete
268  (Triple(Uri(transformUri), m_store->expand("vamp:output"), Node()));
269 
270  if (outputNode == Node()) return true;
271 
272  if (outputNode.type != Node::URI && outputNode.type != Node::Blank) {
273  m_errorString = QString("vamp:output for output of transform <%1> is not a URI or blank node").arg(transformUri);
274  return false;
275  }
276 
277  // Now, outputNode might be the subject of a triple within m_store
278  // that tells us the vamp:identifier, or it might be the subject
279  // of a triple within the indexer that tells us it
280 
281  Node identNode = m_store->complete
282  (Triple(outputNode, m_store->expand("vamp:identifier"), Node()));
283 
284  if (identNode == Node()) {
286  const BasicStore *index = indexer->getIndex();
287  identNode = index->complete
288  (Triple(outputNode, index->expand("vamp:identifier"), Node()));
289  }
290 
291  if (identNode == Node() || identNode.type != Node::Literal) {
292  m_errorString = QString("No vamp:identifier found for output of transform <%1>, or vamp:identifier is not a literal").arg(transformUri);
293  return false;
294  }
295 
296  transform.setOutput(identNode.value);
297 
298  return true;
299 }
300 
301 
302 bool
304  QString transformUri)
305 {
306  Nodes bindings = m_store->match
307  (Triple(Uri(transformUri), m_store->expand("vamp:parameter_binding"), Node())).objects();
308 
309  foreach (Node binding, bindings) {
310 
311  Node paramNode = m_store->complete
312  (Triple(binding, m_store->expand("vamp:parameter"), Node()));
313 
314  if (paramNode == Node()) {
315  cerr << "RDFTransformFactoryImpl::setParameters: No vamp:parameter for binding " << binding << endl;
316  continue;
317  }
318 
319  Node valueNode = m_store->complete
320  (Triple(binding, m_store->expand("vamp:value"), Node()));
321 
322  if (paramNode == Node()) {
323  cerr << "RDFTransformFactoryImpl::setParameters: No vamp:value for binding " << binding << endl;
324  continue;
325  }
326 
327  // As with output above, paramNode might be the subject of a
328  // triple within m_store that tells us the vamp:identifier, or
329  // it might be the subject of a triple within the indexer that
330  // tells us it
331 
332  Node idNode = m_store->complete
333  (Triple(paramNode, m_store->expand("vamp:identifier"), Node()));
334 
335  if (idNode == Node()) {
337  const BasicStore *index = indexer->getIndex();
338  idNode = index->complete
339  (Triple(paramNode, index->expand("vamp:identifier"), Node()));
340  }
341 
342  if (idNode == Node() || idNode.type != Node::Literal) {
343  cerr << "RDFTransformFactoryImpl::setParameters: No vamp:identifier for parameter " << paramNode << endl;
344  continue;
345  }
346 
347  transform.setParameter(idNode.value, valueNode.value.toFloat());
348  }
349 
350  return true;
351 }
352 
353 QString
355  QString uri)
356 {
357  QString str;
358  QTextStream s(&str);
359 
360  // assumes the usual prefixes are available; requires that uri be
361  // a local fragment (e.g. ":transform") rather than a uri enclosed
362  // in <>, so that we can suffix it if need be
363 
364  QString pluginId = transform.getPluginIdentifier();
365  QString pluginUri = PluginRDFIndexer::getInstance()->getURIForPluginId(pluginId);
366 
367  if (pluginUri != "") {
368  s << uri << " a vamp:Transform ;" << endl;
369  s << " vamp:plugin <" << QUrl(pluginUri).toEncoded().data() << "> ;" << endl;
370  } else {
371  cerr << "WARNING: RDFTransformFactory::writeTransformToRDF: No plugin URI available for plugin id \"" << pluginId << "\", writing synthetic plugin and library resources" << endl;
372  QString type, soname, label;
373  PluginIdentifier::parseIdentifier(pluginId, type, soname, label);
374  s << uri << "_plugin a vamp:Plugin ;" << endl;
375  s << " vamp:identifier \"" << label << "\" .\n" << endl;
376  s << uri << "_library a vamp:PluginLibrary ;" << endl;
377  s << " vamp:identifier \"" << soname << "\" ;" << endl;
378  s << " vamp:available_plugin " << uri << "_plugin .\n" << endl;
379  s << uri << " a vamp:Transform ;" << endl;
380  s << " vamp:plugin " << uri << "_plugin ;" << endl;
381  }
382 
383  PluginRDFDescription description(pluginId);
384  QString outputId = transform.getOutput();
385  QString outputUri = description.getOutputUri(outputId);
386 
387  if (transform.getOutput() != "" && outputUri == "") {
388  cerr << "WARNING: RDFTransformFactory::writeTransformToRDF: No output URI available for transform output id \"" << transform.getOutput() << "\", writing a synthetic output resource" << endl;
389  }
390 
391  if (transform.getStepSize() != 0) {
392  s << " vamp:step_size \"" << transform.getStepSize() << "\"^^xsd:int ; " << endl;
393  }
394  if (transform.getBlockSize() != 0) {
395  s << " vamp:block_size \"" << transform.getBlockSize() << "\"^^xsd:int ; " << endl;
396  }
397  if (transform.getStartTime() != RealTime::zeroTime) {
398  s << " vamp:start \"" << transform.getStartTime().toXsdDuration().c_str() << "\"^^xsd:duration ; " << endl;
399  }
400  if (transform.getDuration() != RealTime::zeroTime) {
401  s << " vamp:duration \"" << transform.getDuration().toXsdDuration().c_str() << "\"^^xsd:duration ; " << endl;
402  }
403  if (transform.getSampleRate() != 0) {
404  s << " vamp:sample_rate \"" << transform.getSampleRate() << "\"^^xsd:float ; " << endl;
405  }
406 
407  QString program = transform.getProgram();
408  if (program != "") {
409  s << " vamp:program \"\"\"" << program << "\"\"\" ;" << endl;
410  }
411 
412  QString summary = transform.summaryTypeToString(transform.getSummaryType());
413  if (summary != "") {
414  s << " vamp:summary_type \"" << summary << "\" ;" << endl;
415  }
416 
417  Transform::ParameterMap parameters = transform.getParameters();
418  for (Transform::ParameterMap::const_iterator i = parameters.begin();
419  i != parameters.end(); ++i) {
420  QString name = i->first;
421  float value = i->second;
422  s << " vamp:parameter_binding [" << endl;
423  s << " vamp:parameter [ vamp:identifier \"" << name << "\" ] ;" << endl;
424  s << " vamp:value \"" << value << "\"^^xsd:float ;" << endl;
425  s << " ] ;" << endl;
426  }
427 
428  if (outputUri != "") {
429  s << " vamp:output <" << QUrl(outputUri).toEncoded().data() << "> ." << endl;
430  } else if (outputId != "") {
431  s << " vamp:output [ vamp:identifier \"" << outputId << "\" ] ." << endl;
432  } else {
433  s << " ." << endl;
434  }
435 
436  return str;
437 }
438 
std::vector< Transform > getTransforms(ProgressReporter *)
SummaryType getSummaryType() const
Definition: Transform.cpp:311
QString getURIForPluginId(QString pluginId)
void setSampleRate(float rate)
Definition: Transform.cpp:389
void setDuration(RealTime d)
Definition: Transform.cpp:377
static QString getKnownExtensions()
float getSampleRate() const
Definition: Transform.cpp:383
QString getErrorString() const
void setWindowType(WindowType type)
Definition: Transform.cpp:353
Definition: Window.h:40
QString getProgram() const
Definition: Transform.cpp:299
std::string toXsdDuration() const
Return a string in xsd:duration format.
Definition: RealTime.cpp:390
QString getIdForPluginURI(QString uri)
static void parseIdentifier(QString identifier, QString &type, QString &soName, QString &label)
void setStartTime(RealTime t)
Definition: Transform.cpp:365
QString getOutput() const
Definition: Transform.cpp:224
bool setParameters(Transform &, QString)
const Dataquay::BasicStore * getIndex()
void setOutput(QString output)
Definition: Transform.cpp:236
void setPluginIdentifier(QString pluginIdentifier)
Definition: Transform.cpp:230
bool setOutput(Transform &, QString)
virtual QString toXmlString(QString indent="", QString extraAttributes="") const
Convert this exportable object to XML in a string.
static QString writeTransformToRDF(const Transform &, QString uri)
RealTime getStartTime() const
Definition: Transform.cpp:359
QString getOutputUri(QString outputId) const
RDFTransformFactoryImpl * m_d
int getStepSize() const
Definition: Transform.cpp:323
void setBlockSize(int s)
Definition: Transform.cpp:341
RDFTransformFactory(QString url)
std::map< QString, float > ParameterMap
Definition: Transform.h:85
std::vector< Transform > getTransforms(ProgressReporter *reporter)
static SummaryType stringToSummaryType(QString)
Definition: Transform.cpp:450
const ParameterMap & getParameters() const
Definition: Transform.cpp:249
void setSummaryType(SummaryType type)
Definition: Transform.cpp:317
int getBlockSize() const
Definition: Transform.cpp:335
void setParameter(QString name, float value)
Definition: Transform.cpp:261
static PluginRDFIndexer * getInstance()
static QString writeTransformToRDF(const Transform &, QString)
void setProgram(QString program)
Definition: Transform.cpp:305
static const RealTime zeroTime
Definition: RealTime.h:159
static RealTime fromXsdDuration(std::string xsdd)
Definition: RealTime.cpp:78
QString getPluginIdentifier() const
Definition: Transform.cpp:218
static QString summaryTypeToString(SummaryType)
Definition: Transform.cpp:470
void setStepSize(int s)
Definition: Transform.cpp:329
RealTime getDuration() const
Definition: Transform.cpp:371