Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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="")