Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkRdfStore.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkRdfStore.h"
18 
19 #include <iostream>
20 
21 #include <redland.h>
22 
23 namespace mitk {
24  class RdfStorePrivate
25  {
26  public:
27  typedef std::map<std::string, std::list<RdfNode> > ResultMap;
28  typedef std::map<std::string, RdfUri> PrefixMap;
29 
30  RdfStorePrivate();
31  ~RdfStorePrivate();
32 
33  void SetBaseUri(RdfUri uri);
34  RdfUri GetBaseUri() const;
35 
36  void AddPrefix(std::string prefix, RdfUri uri);
37  PrefixMap GetPrefixes() const;
38 
39  void CleanUp();
40 
41  bool Add(RdfTriple triple);
42  bool Remove(RdfTriple triple);
43  bool Contains(RdfTriple triple);
44 
45  ResultMap ExecuteTupleQuery(const std::string& query) const;
46  bool ExecuteBooleanQuery(const std::string& query) const;
47 
48  void Save(std::string filename, std::string format = "");
49  void Import(std::string url, std::string format = "");
50 
51  RdfUri m_BaseUri;
52 
53  PrefixMap m_Prefixes;
54 
55  librdf_world* m_World;
56  librdf_storage* m_Storage;
57  librdf_model* m_Model;
58 
59  librdf_statement* RdfTripleToStatement(RdfTriple triple) const;
60  librdf_node* RdfNodeToLibRdfNode(RdfNode node) const;
61  librdf_uri* RdfUriToLibRdfUri(RdfUri uri) const;
62 
63  RdfTriple StatementToRdfTriple(librdf_statement* statement) const;
64  RdfNode LibRdfNodeToRdfNode(librdf_node* node) const;
65  RdfUri LibRdfUriToRdfUri(librdf_uri* uri) const;
66 
67  bool CheckComplete(librdf_statement* statement);
68 
69  private:
70 
77  std::string PrependPrefixes(const std::string& query) const;
78 
79  };
80 
81  /****************************************************************************
82  **************************** mitkRdfStorePrivate ****************************
83  ****************************************************************************/
84 
85  RdfStorePrivate::RdfStorePrivate()
86  : m_World(0), m_Storage(0), m_Model(0)
87  {
88  // SetUp base prefixes
89  m_Prefixes["rdf"] = RdfUri("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
90  m_Prefixes["rdfs"] = RdfUri("http://www.w3.org/2000/01/rdf-schema#");
91  m_Prefixes["xsd"] = RdfUri("http://www.w3.org/2001/XMLSchema#");
92  m_Prefixes["owl"] = RdfUri("http://www.w3.org/2002/07/owl#");
93 
94  // SetUp new store
95  CleanUp();
96  }
97 
98  RdfStorePrivate::~RdfStorePrivate()
99  {
100  if(m_Model)
101  librdf_free_model(m_Model);
102  if(m_Storage)
103  librdf_free_storage(m_Storage);
104  if(m_World)
105  librdf_free_world(m_World);
106  }
107 
108  void RdfStorePrivate::SetBaseUri(RdfUri uri)
109  {
110  m_BaseUri = uri;
111  m_Prefixes[""] = RdfUri(m_BaseUri.ToString());
112  }
113 
114  RdfUri RdfStorePrivate::GetBaseUri() const
115  {
116  return m_BaseUri;
117  }
118 
119  void RdfStorePrivate::AddPrefix(std::string prefix, RdfUri uri)
120  {
121  m_Prefixes[prefix] = uri;
122  }
123 
124  RdfStorePrivate::PrefixMap RdfStorePrivate::GetPrefixes() const
125  {
126  return m_Prefixes;
127  }
128 
129  void RdfStorePrivate::CleanUp()
130  {
131  // CleanUp old Store if there is one
132  if(m_Model)
133  librdf_free_model(m_Model);
134  if(m_Storage)
135  librdf_free_storage(m_Storage);
136  if(m_World)
137  librdf_free_world(m_World);
138 
139  // SetUp new Store
140  m_World = librdf_new_world();
141  librdf_world_open(m_World);
142 
143  m_Storage = librdf_new_storage(m_World, "memory", 0, 0);
144 
145  if(!m_Storage)
146  {
147  mitkThrow() << "RDF Library Error";
148  }
149 
150  m_Model = librdf_new_model(m_World, m_Storage, 0);
151 
152  if(!m_Model)
153  {
154  mitkThrow() << "RDF Library Error";
155  }
156  }
157 
158  bool RdfStorePrivate::Add(RdfTriple triple)
159  {
160  librdf_statement* statement = RdfTripleToStatement(triple);
161 
162  if (!CheckComplete(statement))
163  {
164  librdf_free_statement(statement);
165  return false;
166  }
167 
168  // Store already contains statement
169  if (Contains(triple)) return true;
170 
171  if (librdf_model_add_statement(m_Model, statement) != 0) {
172  librdf_free_statement(statement);
173  return false;
174  }
175  else
176  {
177  librdf_free_statement(statement);
178  return true;
179  }
180  }
181 
182  bool RdfStorePrivate::Remove(RdfTriple triple)
183  {
184  librdf_statement* statement = RdfTripleToStatement(triple);
185 
186  if (!CheckComplete(statement))
187  {
188  librdf_free_statement(statement);
189  return false;
190  }
191 
192  // Store does not contain statement
193  if (!Contains(triple)) return true;
194 
195  if (librdf_model_remove_statement(m_Model, statement) != 0) {
196  librdf_free_statement(statement);
197  return false;
198  }
199  else
200  {
201  librdf_free_statement(statement);
202  return true;
203  }
204  return false;
205  }
206 
207  bool RdfStorePrivate::Contains(RdfTriple triple)
208  {
209  librdf_statement* statement = RdfTripleToStatement(triple);
210 
211  // if 0 there is no triple
212  if (librdf_model_contains_statement(m_Model, statement) == 0) {
213  librdf_free_statement(statement);
214  return false;
215  }
216  else
217  {
218  librdf_free_statement(statement);
219  return true;
220  }
221  return false;
222  }
223 
224  RdfStorePrivate::ResultMap RdfStorePrivate::ExecuteTupleQuery(const std::string& query) const
225  {
226  RdfStorePrivate::ResultMap resultMap;
227 
228  const std::string completeQuery = this->PrependPrefixes(query);
229 
230  librdf_query* rdfQuery = librdf_new_query(m_World, "sparql", 0, (const unsigned char*) completeQuery.c_str(), 0);
231 
232  if (!rdfQuery) return resultMap;
233 
234  librdf_query_results* results = librdf_query_execute(rdfQuery, m_Model);
235 
236  if (!results)
237  {
238  librdf_free_query(rdfQuery);
239  return resultMap;
240  }
241 
242  if (!librdf_query_results_is_bindings(results))
243  {
244  librdf_free_query_results(results);
245  librdf_free_query(rdfQuery);
246  return resultMap;
247  }
248 
249  while (!librdf_query_results_finished(results))
250  {
251  int count = librdf_query_results_get_bindings_count(results);
252 
253  for (int i = 0; i < count; ++i)
254  {
255  const char *name = librdf_query_results_get_binding_name(results, i);
256 
257  if (!name) continue;
258 
259  std::string key = name;
260 
261  std::list<RdfNode> list;
262 
263  if(!resultMap[key].empty())
264  {
265  list = resultMap[key];
266  }
267 
268  librdf_node *node = librdf_query_results_get_binding_value(results, i);
269 
270  list.push_back(LibRdfNodeToRdfNode(node));
271 
272  resultMap[key] = list;
273  }
274 
275  librdf_query_results_next(results);
276  }
277 
278  librdf_free_query_results(results);
279  librdf_free_query(rdfQuery);
280 
281  return resultMap;
282  }
283 
284  bool RdfStorePrivate::ExecuteBooleanQuery(const std::string& query) const
285  {
286  const std::string completeQuery = this->PrependPrefixes(query);
287 
288  librdf_query* rdfQuery = librdf_new_query(m_World, "sparql", 0, (const unsigned char*) completeQuery.c_str(), 0);
289 
290  if (!rdfQuery)
291  {
292  mitkThrow() << "failed to create query object";
293  }
294 
295  librdf_query_results* results = librdf_query_execute(rdfQuery, m_Model);
296 
297  if (!results)
298  {
299  librdf_free_query(rdfQuery);
300  mitkThrow() << "SPARQL syntax error";
301  }
302 
303  if (!librdf_query_results_is_boolean(results))
304  {
305  librdf_free_query_results(results);
306  librdf_free_query(rdfQuery);
307 
308  mitkThrow() << "unexpected result type error: tried to request a boolean result with a non-boolean query";
309  }
310 
311  int rawResult = librdf_query_results_get_boolean(results);
312 
313  bool booleanResult;
314 
315  if (rawResult > 0)
316  {
317  booleanResult = true;
318  }
319  else if (rawResult == 0)
320  {
321  booleanResult = false;
322  }
323  else
324  {
325  mitkThrow() << "error while retrieving result";
326  }
327 
328  librdf_free_query_results(results);
329  librdf_free_query(rdfQuery);
330 
331  return booleanResult;
332  }
333 
334  void RdfStorePrivate::Save(std::string filename, std::string format)
335  {
336  if (format == "") format = "turtle";
337 
338  librdf_uri* baseUri = RdfUriToLibRdfUri(m_BaseUri);
339 
340  librdf_serializer* s = librdf_new_serializer(m_World, format.c_str(), 0, 0);
341 
342  if(!s)
343  {
344  mitkThrow() << "RDF Library Error";
345  }
346 
347  for (PrefixMap::const_iterator i = m_Prefixes.begin(); i != m_Prefixes.end(); i++)
348  {
349  librdf_serializer_set_namespace(s, RdfUriToLibRdfUri(i->second), i->first.c_str());
350  }
351 
352  FILE* f = fopen(filename.c_str(), "w+");
353 
354  librdf_serializer_serialize_model_to_file_handle(s, f, baseUri, m_Model);
355 
356  librdf_free_serializer(s);
357  librdf_free_uri(baseUri);
358  fclose(f);
359  }
360 
361  void RdfStorePrivate::Import(std::string url, std::string format)
362  {
363  std::string baseUri = m_BaseUri.ToString();
364 
365  if (baseUri.empty())
366  {
367  baseUri = url;
368  SetBaseUri(RdfUri(baseUri));
369  }
370 
371  if (format == "") format= "turtle";
372 
373  // Redland uses file paths like file:YOURPATH ( Example: file:D:/home/readme.txt )
374  librdf_uri* uri = librdf_new_uri(m_World, (const unsigned char*) url.c_str());
375 
376  librdf_uri* libRdfBaseUri = librdf_new_uri(m_World, (const unsigned char*) baseUri.c_str());
377 
378  librdf_parser* p = librdf_new_parser(m_World, format.c_str(), 0, 0);
379 
380  if(!p)
381  {
382  mitkThrow() << "RDF Library Error";
383  }
384 
385  if (librdf_parser_parse_into_model(p, uri, libRdfBaseUri, m_Model) != 0 )
386  {
387  librdf_free_parser(p);
388  MITK_ERROR << "Parsing into Model failed.";
389  return;
390  }
391 
392  int namespaces = librdf_parser_get_namespaces_seen_count(p);
393 
394  for (int i = 0; i < namespaces; i++) {
395  const char* prefixChar = librdf_parser_get_namespaces_seen_prefix(p, i);
396 
397  if ( !prefixChar ) continue;
398 
399  std::string prefix = prefixChar;
400  RdfUri uri = LibRdfUriToRdfUri(librdf_parser_get_namespaces_seen_uri(p, i));
401 
402  if (uri == RdfUri()) return;
403 
404  RdfStorePrivate::PrefixMap::iterator it = m_Prefixes.find(prefix);
405 
406  // map iterator is equal to iterator-end so it is not already added
407  if (it == m_Prefixes.end()) {
408  AddPrefix(prefix, uri);
409  }
410  }
411  librdf_free_parser(p);
412  }
413 
414  bool RdfStorePrivate::CheckComplete(librdf_statement* statement)
415  {
416  if (librdf_statement_is_complete(statement) != 0) return true;
417  else return false;
418  }
419 
420  librdf_statement* RdfStorePrivate::RdfTripleToStatement(RdfTriple triple) const
421  {
422  librdf_node* subject = RdfNodeToLibRdfNode(triple.GetTripleSubject());
423  librdf_node* predicate = RdfNodeToLibRdfNode(triple.GetTriplePredicate());
424  librdf_node* object = RdfNodeToLibRdfNode(triple.GetTripleObject());
425 
426  librdf_statement* statement = librdf_new_statement_from_nodes(m_World, subject, predicate, object);
427  if(!statement) return 0;
428  return statement;
429  }
430 
431  librdf_node* RdfStorePrivate::RdfNodeToLibRdfNode(RdfNode node) const
432  {
433  librdf_node* newNode = 0;
434 
435  switch (node.GetType())
436  {
437  case RdfNode::NOTHING:
438  break;
439  case RdfNode::BLANK:
440  newNode = librdf_new_node_from_blank_identifier(m_World, (const unsigned char*) node.GetValue().c_str());
441  break;
442  case RdfNode::LITERAL:
443  {
444  if (node.GetDatatype() != RdfUri())
445  {
446  librdf_uri* typeUri = RdfUriToLibRdfUri(node.GetDatatype());
447  newNode = librdf_new_node_from_typed_literal(m_World, (const unsigned char*) node.GetValue().c_str(), 0, typeUri);
448  }
449  else
450  {
451  newNode = librdf_new_node_from_literal(m_World, (const unsigned char*) node.GetValue().c_str(), 0, 0);
452  }
453  }
454  break;
455  case RdfNode::URI:
456  newNode = librdf_new_node_from_uri( m_World, librdf_new_uri(m_World, (const unsigned char*) node.GetValue().c_str()) );
457  break;
458  default:
459  break;
460  }
461  return newNode;
462  }
463 
464  librdf_uri* RdfStorePrivate::RdfUriToLibRdfUri(RdfUri uri) const
465  {
466  librdf_uri* libUri = librdf_new_uri(m_World, (const unsigned char*) uri.ToString().c_str());
467  if (!libUri) return 0;
468  return libUri;
469  }
470 
471  RdfTriple RdfStorePrivate::StatementToRdfTriple(librdf_statement* statement) const
472  {
473  librdf_node *subject = librdf_statement_get_subject(statement);
474  librdf_node *predicate = librdf_statement_get_predicate(statement);
475  librdf_node *object = librdf_statement_get_object(statement);
476 
477  RdfTriple triple(LibRdfNodeToRdfNode(subject),
478  LibRdfNodeToRdfNode(predicate),
479  LibRdfNodeToRdfNode(object));
480 
481  return triple;
482  }
483 
484  RdfNode RdfStorePrivate::LibRdfNodeToRdfNode(librdf_node* node) const
485  {
486  RdfNode mitkNode;
487 
488  if (!node) return mitkNode;
489 
490  if (librdf_node_is_resource(node))
491  {
492  mitkNode.SetType(RdfNode::URI);
493  librdf_uri *uri = librdf_node_get_uri(node);
494  mitkNode.SetValue(LibRdfUriToRdfUri(uri).ToString());
495  }
496  else if (librdf_node_is_literal(node))
497  {
498  mitkNode.SetType(RdfNode::LITERAL);
499  std::string value = (const char*) librdf_node_get_literal_value(node);
500  if (!value.empty()) mitkNode.SetValue(value);
501  librdf_uri* typeUri = librdf_node_get_literal_value_datatype_uri(node);
502  if (typeUri) mitkNode.SetDatatype(LibRdfUriToRdfUri(typeUri));
503  }
504  else if (librdf_node_is_blank(node))
505  {
506  mitkNode.SetType(RdfNode::BLANK);
507  std::string str = (const char*) librdf_node_get_blank_identifier(node);
508  if (!str.empty()) mitkNode.SetValue(str);
509  }
510  return mitkNode;
511  }
512 
513  RdfUri RdfStorePrivate::LibRdfUriToRdfUri(librdf_uri* uri) const
514  {
515  std::string str = (const char*) librdf_uri_as_string(uri);
516  if (!str.empty()) return RdfUri(str);
517 
518  return RdfUri();
519  }
520 
521  std::string RdfStorePrivate::PrependPrefixes(const std::string& query) const
522  {
523  std::string completeQuery;
524 
525  for (PrefixMap::const_iterator i = m_Prefixes.begin(); i != m_Prefixes.end(); i++)
526  {
527  completeQuery += "PREFIX " + i->first + ": " + "<" + i->second.ToString() + "> ";
528  }
529 
530  return completeQuery += query;
531  }
532 
533  /****************************************************************************
534  ******************************* mitkRdfStore ********************************
535  ****************************************************************************/
536 
537  typedef std::map<std::string, std::list<RdfNode> > ResultMap;
538  typedef std::map<std::string, RdfUri> PrefixMap;
539 
541  :d(new RdfStorePrivate)
542  {
543  }
544 
546  {
547  delete d;
548  }
549 
551  {
552  d->SetBaseUri(uri);
553  }
554 
556  {
557  return d->GetBaseUri();
558  }
559 
560  void RdfStore::AddPrefix(std::string prefix, RdfUri uri)
561  {
562  d->AddPrefix(prefix, uri);
563  }
564 
565  PrefixMap RdfStore::GetPrefixes() const
566  {
567  return d->GetPrefixes();
568  }
569 
571  {
572  d->CleanUp();
573  }
574 
576  {
577  return d->Add(triple);
578  }
579 
581  {
582  return d->Remove(triple);
583  }
584 
586  {
587  return d->Contains(triple);
588  }
589 
590  ResultMap RdfStore::Query(const std::string& query) const
591  {
592  return d->ExecuteTupleQuery(query);
593  }
594 
595  ResultMap RdfStore::ExecuteTupleQuery(const std::string& query) const
596  {
597  return d->ExecuteTupleQuery(query);
598  }
599 
600  bool RdfStore::ExecuteBooleanQuery(const std::string& query) const
601  {
602  return d->ExecuteBooleanQuery(query);
603  }
604 
605  void RdfStore::Save(std::string filename, std::string format)
606  {
607  d->Save(filename, format);
608  }
609 
610  void RdfStore::Import(std::string url, std::string format)
611  {
612  d->Import(url, format);
613  }
614 } // end of namespace mitk
bool ExecuteBooleanQuery(const std::string &query) const
#define MITK_ERROR
Definition: mitkLogMacros.h:24
ResultMap Query(const std::string &query) const
bool Contains(RdfTriple triple)
void SetBaseUri(RdfUri uri)
DataCollection - Class to facilitate loading/accessing structured data.
void Import(std::string url, std::string format="")
bool Remove(RdfTriple triple)
void AddPrefix(std::string prefix, RdfUri uri)
bool Add(RdfTriple triple)
ResultMap ExecuteTupleQuery(const std::string &query) const
std::map< std::string, std::list< RdfNode > > ResultMap
PrefixMap GetPrefixes() const
static const std::string filename
#define mitkThrow()
RdfUri GetBaseUri() const
std::map< std::string, RdfUri > PrefixMap
void Save(std::string filename, std::string format="")