diff options
-rw-r--r-- | configure.ac | 35 | ||||
-rw-r--r-- | raul/AtomRedland.h (renamed from raul/AtomRaptor.h) | 48 | ||||
-rw-r--r-- | raul/Makefile.am | 30 | ||||
-rw-r--r-- | raul/Namespaces.h | 2 | ||||
-rw-r--r-- | raul/RDFModel.h | 82 | ||||
-rw-r--r-- | raul/RDFNode.h | 75 | ||||
-rw-r--r-- | raul/RDFQuery.h | 23 | ||||
-rw-r--r-- | raul/RDFWorld.h | 60 | ||||
-rw-r--r-- | raul/RDFWriter.h | 85 | ||||
-rw-r--r-- | raul/Stateful.h | 13 | ||||
-rw-r--r-- | src/Makefile.am | 21 | ||||
-rw-r--r-- | src/Namespaces.cpp | 4 | ||||
-rw-r--r-- | src/RDFModel.cpp | 215 | ||||
-rw-r--r-- | src/RDFNode.cpp | 140 | ||||
-rw-r--r-- | src/RDFQuery.cpp | 60 | ||||
-rw-r--r-- | src/RDFWorld.cpp | 95 | ||||
-rw-r--r-- | src/RDFWriter.cpp | 257 | ||||
-rw-r--r-- | tests/Makefile.am | 9 | ||||
-rw-r--r-- | tests/rdf_test.cpp | 8 |
19 files changed, 799 insertions, 463 deletions
diff --git a/configure.ac b/configure.ac index 910763b..f6bb874 100644 --- a/configure.ac +++ b/configure.ac @@ -82,25 +82,21 @@ if test "$build_jack" = "yes"; then fi AM_CONDITIONAL(WITH_JACK, [test "$build_jack" = "yes"]) -build_raptor="yes" -AC_ARG_ENABLE(raptor, - [AS_HELP_STRING(--enable-raptor, [Include Raptor (RDF) serialization support (yes)])], - [ if test x$enable_raptor = xno ; then build_raptor=no ; fi ]) -if test "$build_raptor" = "yes"; then - PKG_CHECK_MODULES(RAPTOR, raptor >= 1.4.15, [], - AC_MSG_ERROR([RDF support requires raptor (>= 1.4.15)])) -fi -AM_CONDITIONAL(WITH_RAPTOR, [test "$build_raptor" = "yes"]) - -build_rasqal="yes" -AC_ARG_ENABLE(rasqal, - [AS_HELP_STRING(--enable-rasqal, [Include Rasqal (RDF Querying) support (yes)])], - [ if test x$enable_rasqal = xno ; then build_rasqal=no ; fi ]) -if test "$build_rasqal" = "yes"; then - PKG_CHECK_MODULES(RASQAL, rasqal >= 0.9.11, [], - AC_MSG_ERROR([RDF query support requires rasqal (>= 0.9.11)])) +# Check for Redland +#PKG_CHECK_MODULES(REDLAND, redland >= 1.0.0) +# No pkg-config?! Booo! +build_redland="no" +AC_CHECK_PROG(REDLAND_CONFIG, redland-config, redland-config) +if test "X$REDLAND_CONFIG" = X; then + AC_MSG_ERROR([SLV2 requires Redland (librdf), but redland-config not found.]) +else + build_redland="yes" + REDLAND_CFLAGS=`$REDLAND_CONFIG --cflags` + REDLAND_LIBS=`$REDLAND_CONFIG --libs` + AC_SUBST(REDLAND_CFLAGS) + AC_SUBST(REDLAND_LIBS) fi -AM_CONDITIONAL(WITH_RASQAL, [test "$build_rasqal" = "yes"]) +AM_CONDITIONAL(WITH_REDLAND, [test "$build_redland" = "yes"]) build_liblo="yes" AC_ARG_ENABLE(liblo, @@ -147,8 +143,7 @@ AC_MSG_RESULT([]) AC_MSG_RESULT([Jack support: $build_jack]) AC_MSG_RESULT([LASH support: $build_lash]) AC_MSG_RESULT([OSC (Liblo) support: $build_liblo]) -AC_MSG_RESULT([RDF Serialization (Raptor) support: $build_raptor]) -AC_MSG_RESULT([RDF Querying (Rasqal) support: $build_rasqal]) +AC_MSG_RESULT([RDF (Redland) support: $build_redland]) AC_MSG_RESULT([Smart Pointers (Boost): $build_smart_pointers]) AC_MSG_RESULT([**********************************************************************]) AC_MSG_RESULT([]) diff --git a/raul/AtomRaptor.h b/raul/AtomRedland.h index 9b50a38..ae4e3b4 100644 --- a/raul/AtomRaptor.h +++ b/raul/AtomRedland.h @@ -15,13 +15,13 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef RAUL_ATOM_RAPTOR_H -#define RAUL_ATOM_RAPTOR_H +#ifndef RAUL_ATOM_REDLAND_H +#define RAUL_ATOM_REDLAND_H #include <iostream> #include <sstream> #include <cstring> -#include <raptor.h> +#include <librdf.h> #include "raul/Atom.h" using std::cerr; using std::endl; @@ -30,51 +30,53 @@ using std::cerr; using std::endl; namespace Raul { -/** Support for serializing an Atom to/from RDF (via raptor, a part of librdf). +/** Support for serializing an Atom to/from RDF (via librdf). * - * (Here to prevent a unnecessary raptor dependency for Atom). + * (Here to prevent a unnecessary reddland dependency for Atom). * * \ingroup raul */ -class AtomRaptor { +class AtomRedland { public: /** Set this atom's value to the object (value) portion of an RDF triple. * * Caller is responsible for calling free(triple->object). */ - static void atom_to_triple_object(raptor_statement* triple, const Atom& atom) { + static librdf_node* atom_to_rdf_node(librdf_world* world, + const Atom& atom) + { std::ostringstream os; - triple->object_literal_language = NULL; + librdf_uri* type = NULL; + librdf_node* node = NULL; + std::string str; switch (atom.type()) { case Atom::INT: os << atom.get_int32(); - triple->object = (unsigned char*)strdup(os.str().c_str()); - triple->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL; - triple->object_literal_datatype = raptor_new_uri( - U("http://www.w3.org/2001/XMLSchema#integer")); + str = os.str(); + // xsd:integer -> pretty integer literals in Turtle + type = librdf_new_uri(world, U("http://www.w3.org/2001/XMLSchema#integer")); break; case Atom::FLOAT: os << atom.get_float(); - triple->object = (unsigned char*)strdup(os.str().c_str()); - triple->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL; - /* Use xsd:decimal so turtle abbreviation works */ - triple->object_literal_datatype = raptor_new_uri( - U("http://www.w3.org/2001/XMLSchema#decimal")); + str = os.str(); + // xsd:decimal -> pretty decimal (float) literals in Turtle + type = librdf_new_uri(world, U("http://www.w3.org/2001/XMLSchema#decimal")); break; case Atom::STRING: - triple->object = strdup(atom.get_string()); - triple->object_type = RAPTOR_IDENTIFIER_TYPE_LITERAL; - triple->object_literal_datatype = NULL; + str = atom.get_string(); break; case Atom::BLOB: case Atom::NIL: default: cerr << "WARNING: Unserializable Atom!" << endl; - triple->object = NULL; - triple->object_type = RAPTOR_IDENTIFIER_TYPE_UNKNOWN; } + + if (str != "") + node = librdf_new_node_from_typed_literal(world, U(str.c_str()), NULL, type); + + return node; } #if 0 @@ -102,4 +104,4 @@ public: } // namespace Raul -#endif // RAUL_ATOM_RAPTOR_H +#endif // RAUL_ATOM_REDLAND_H diff --git a/raul/Makefile.am b/raul/Makefile.am index bc22299..907a95d 100644 --- a/raul/Makefile.am +++ b/raul/Makefile.am @@ -1,48 +1,48 @@ raulincludedir = $(includedir)/raul raulinclude_HEADERS = \ - types.h \ - midi_events.h \ Array.h \ Atom.h \ - AtomLiblo.h \ - AtomRaptor.h \ AtomicInt.h \ AtomicPtr.h \ - DoubleBuffer.h \ Condition.h \ Deletable.h \ + DoubleBuffer.h \ JackDriver.h \ List.h \ + MIDIRingBuffer.h \ + MIDISink.h \ Maid.h \ Mutex.h \ Namespaces.h \ Path.h \ Process.h \ + Quantizer.h \ + RDFModel.h \ + RDFNode.h \ RDFQuery.h \ - RDFWriter.h \ + RDFWorld.h \ + RingBuffer.h \ + SMFReader.h \ + SMFWriter.h \ SRMWQueue.h \ SRSWQueue.h \ - RingBuffer.h \ Semaphore.h \ SharedPtr.h \ Slave.h \ Stateful.h \ Thread.h \ - WeakPtr.h \ TimeSlice.h \ - Quantizer.h \ - MIDIRingBuffer.h \ - MIDISink.h \ - SMFReader.h \ - SMFWriter.h + WeakPtr.h \ + midi_events.h \ + types.h if WITH_LIBLO raulinclude_HEADERS += AtomLiblo.h endif -if WITH_RAPTOR -raulinclude_HEADERS += AtomRaptor.h +if WITH_REDLAND +raulinclude_HEADERS += AtomRedland.h endif if WITH_LASH diff --git a/raul/Namespaces.h b/raul/Namespaces.h index f81b7b8..673bbd5 100644 --- a/raul/Namespaces.h +++ b/raul/Namespaces.h @@ -28,7 +28,7 @@ namespace Raul { */ class Namespaces : public std::map<std::string, std::string> { public: - std::string qualify(std::string uri); + std::string qualify(std::string uri) const; }; diff --git a/raul/RDFModel.h b/raul/RDFModel.h new file mode 100644 index 0000000..63cdb9d --- /dev/null +++ b/raul/RDFModel.h @@ -0,0 +1,82 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Raul is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RDFMODEL_H +#define RDFMODEL_H + +#include <stdexcept> +#include <string> +#include <librdf.h> +#include <glibmm/ustring.h> +#include <boost/utility.hpp> +#include "raul/Namespaces.h" +#include "raul/Atom.h" +#include "raul/RDFNode.h" + + +namespace Raul { +namespace RDF { + +class World; + + +class Model : public boost::noncopyable { +public: + Model(World& world); + Model(World& world, const Glib::ustring& uri); + ~Model(); + + void serialize_to_file_handle(FILE* fd); + void serialize_to_file(const std::string& file); + std::string serialize_to_string(); + + void add_statement(const Node& subject, + const Node& predicate, + const Node& object); + + void add_statement(const Node& subject, + const std::string& predicate, + const Node& object); + + void add_statement(const Node& subject, + const Node& predicate, + const Atom& object); + + void add_statement(const Node& subject, + const std::string& predicate, + const Atom& object); + + World& world() const { return _world; } + +private: + friend class Query; + + void setup_prefixes(); + + World& _world; + librdf_storage* _storage; + librdf_model* _model; + librdf_serializer* _serializer; + + size_t _next_blank_id; +}; + + +} // namespace RDF +} // namespace Raul + +#endif // RDFMODEL_H diff --git a/raul/RDFNode.h b/raul/RDFNode.h new file mode 100644 index 0000000..cefaf42 --- /dev/null +++ b/raul/RDFNode.h @@ -0,0 +1,75 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Raul is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RDFNODE_H +#define RDFNODE_H + +#include <stdexcept> +#include <string> +#include <librdf.h> +#include "raul/Atom.h" + +namespace Raul { +namespace RDF { + +class World; + + +class Node { +public: + // Matches librdf_node_type + enum Type { UNKNOWN=0, RESOURCE, LITERAL, BLANK }; + + Node() : _node(NULL) {} + + Node(World& world, Type t, const std::string& s); + Node(World& world); + Node(librdf_node* node); + Node(const Node& other); + ~Node(); + + Type type() const { return ((_node) ? (Type)librdf_node_get_type(_node) : UNKNOWN); } + + librdf_node* get_node() const { return _node; } + + operator bool() const { return (_node != NULL); } + + const Node& operator=(const Node& other) { + if (_node) + librdf_free_node(_node); + _node = (other._node) ? librdf_new_node_from_node(other._node) : NULL; + return *this; + } + + std::string to_string() const; + std::string to_quoted_uri_string() const; + + bool is_int(); + int to_int(); + + bool is_float(); + float to_float(); + +private: + librdf_node* _node; +}; + + +} // namespace RDF +} // namespace Raul + +#endif // RDFNODE_H diff --git a/raul/RDFQuery.h b/raul/RDFQuery.h index 1aa1cad..eef52bd 100644 --- a/raul/RDFQuery.h +++ b/raul/RDFQuery.h @@ -21,25 +21,30 @@ #include <map> #include <list> #include <glibmm/ustring.h> +#include "raul/RDFWorld.h" #include "raul/Namespaces.h" namespace Raul { +namespace RDF { + +class World; +class Model; /** Pretty wrapper for a SPARQL query. * - * Automatically handles things like prepending prefixes, etc. Raul specific. + * Automatically handles things like prepending prefixes, etc. */ -class RDFQuery { +class Query { public: - typedef std::map<Glib::ustring, Glib::ustring> Bindings; - typedef std::list<Bindings> Results; + typedef std::map<std::string, Node> Bindings; // FIXME: order? better to use int + typedef std::list<Bindings> Results; - RDFQuery(const Namespaces& prefixes, Glib::ustring query) + Query(const World& world, Glib::ustring query) { // Prepend prefix header - for (Namespaces::const_iterator i = prefixes.begin(); - i != prefixes.end(); ++i) { + for (Namespaces::const_iterator i = world.prefixes().begin(); + i != world.prefixes().end(); ++i) { _query += "PREFIX "; _query += i->first + ": <" + i->second + ">\n"; } @@ -47,16 +52,16 @@ public: _query += query; } - Results run(const Glib::ustring base_uri) const; + Results run(World& world, Model& model, const Glib::ustring base_uri="") const; Glib::ustring string() const { return _query; }; private: - Glib::ustring _query; }; +} // namespace RDF } // namespace Raul #endif // RAUL_RDFQUERY_H diff --git a/raul/RDFWorld.h b/raul/RDFWorld.h new file mode 100644 index 0000000..8bbd3d1 --- /dev/null +++ b/raul/RDFWorld.h @@ -0,0 +1,60 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Raul is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RDFWORLD_H +#define RDFWORLD_H + +#include <stdexcept> +#include <string> +#include <librdf.h> +#include <boost/utility.hpp> +#include "raul/Namespaces.h" +#include "raul/RDFNode.h" + +namespace Raul { +namespace RDF { + + +class World : public boost::noncopyable { +public: + World(); + ~World(); + + Node blank_id(); + + void add_prefix(const std::string& prefix, const std::string& uri); + std::string expand_uri(const std::string& uri) const; + std::string qualify(const std::string& uri) const; + + const Namespaces& prefixes() const { return _prefixes; } + + librdf_world* world() { return _world; } + +private: + void setup_prefixes(); + + librdf_world* _world; + Namespaces _prefixes; + + size_t _next_blank_id; +}; + + +} // namespace RDF +} // namespace Raul + +#endif // RDFWORLD_H diff --git a/raul/RDFWriter.h b/raul/RDFWriter.h deleted file mode 100644 index 81bd230..0000000 --- a/raul/RDFWriter.h +++ /dev/null @@ -1,85 +0,0 @@ -/* This file is part of Raul. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Raul is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Raul is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef RDFWRITER_H -#define RDFWRITER_H - -#include <stdexcept> -#include <string> -#include <raptor.h> -#include "raul/Namespaces.h" -#include "raul/Atom.h" - -namespace Raul { - - -class RdfId { -public: - enum Type { NULL_ID, ANONYMOUS, RESOURCE }; - - RdfId(Type t, const std::string& s) : _type(t), _string(s) {} - RdfId() : _type(NULL_ID) {} - - Type type() const { return _type; } - const std::string& to_string() const { return _string; } - - operator bool() const { return (_type != NULL_ID); } - -private: - Type _type; - std::string _string; ///< URI or blank node ID, depending on _type -}; - - -class RDFWriter { -public: - RDFWriter(); - - void add_prefix(const std::string& prefix, const std::string& uri); - std::string expand_uri(const std::string& uri); - - void start_to_file_handle(FILE* fd) throw (std::logic_error); - void start_to_filename(const std::string& filename) throw (std::logic_error); - void start_to_string() throw (std::logic_error); - std::string finish() throw (std::logic_error); - - RdfId blank_id(); - - bool serialization_in_progress() { return (_serializer != NULL); } - - void write(const RdfId& subject, - const RdfId& predicate, - const RdfId& object); - - void write(const RdfId& subject, - const RdfId& predicate, - const Atom& object); - -private: - void setup_prefixes(); - - raptor_serializer* _serializer; - unsigned char* _string_output; - Namespaces _prefixes; - - size_t _next_blank_id; -}; - - -} // namespace Raul - -#endif // RDFWRITER_H diff --git a/raul/Stateful.h b/raul/Stateful.h index 5e4626c..a366ffd 100644 --- a/raul/Stateful.h +++ b/raul/Stateful.h @@ -18,25 +18,22 @@ #ifndef STATEFUL_H #define STATEFUL_H -#include "raul/RDFWriter.h" +#include "raul/RDFModel.h" namespace Raul { -class RDFWriter; - - class Stateful { public: virtual ~Stateful() {} - virtual void write_state(RDFWriter& writer) = 0; + virtual void write_state(RDF::Model& model) = 0; - RdfId id() const { return _id; } - void set_id(const RdfId& id) { _id = id; } + RDF::Node id() const { return _id; } + void set_id(const RDF::Node& id) { _id = id; } protected: - RdfId _id; + RDF::Node _id; }; diff --git a/src/Makefile.am b/src/Makefile.am index ce58a21..ce7bb2e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,22 +1,19 @@ -libraul_la_CXXFLAGS = -I$(top_srcdir) @RAPTOR_CFLAGS@ @RASQAL_CFLAGS@ @GLIBMM_CFLAGS@ @JACK_CFLAGS@ @LASH_CFLAGS@ -libraul_la_LIBADD = @RAPTOR_LIBS@ @RASQAL_LIBS@ @GLIBMM_LIBS@ @JACK_LIBS@ @LASH_LIBS@ +libraul_la_CXXFLAGS = -I$(top_srcdir) @REDLAND_CFLAGS@ @GLIBMM_CFLAGS@ @JACK_CFLAGS@ @LASH_CFLAGS@ +libraul_la_LIBADD = @REDLAND_LIBS@ @GLIBMM_LIBS@ @JACK_LIBS@ @LASH_LIBS@ lib_LTLIBRARIES = libraul.la libraul_la_SOURCES = \ - Thread.cpp \ - Path.cpp \ - Namespaces.cpp \ Maid.cpp \ + Namespaces.cpp \ + Path.cpp \ + RDFWorld.cpp \ SMFReader.cpp \ - SMFWriter.cpp - -if WITH_RAPTOR -libraul_la_SOURCES += RDFWriter.cpp -endif + SMFWriter.cpp \ + Thread.cpp -if WITH_RASQAL -libraul_la_SOURCES += RDFQuery.cpp +if WITH_REDLAND +libraul_la_SOURCES += RDFModel.cpp RDFNode.cpp RDFQuery.cpp endif if WITH_JACK diff --git a/src/Namespaces.cpp b/src/Namespaces.cpp index 2f3dd99..5bdb3b9 100644 --- a/src/Namespaces.cpp +++ b/src/Namespaces.cpp @@ -26,9 +26,9 @@ namespace Raul { * Namespaces, @a uri will be returned unmodified. */ std::string -Namespaces::qualify(std::string uri) +Namespaces::qualify(std::string uri) const { - for (iterator i = begin(); i != end(); ++i) { + for (const_iterator i = begin(); i != end(); ++i) { size_t ns_len = i->second.length(); if (uri.substr(0, ns_len) == i->second) diff --git a/src/RDFModel.cpp b/src/RDFModel.cpp new file mode 100644 index 0000000..d05864f --- /dev/null +++ b/src/RDFModel.cpp @@ -0,0 +1,215 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Raul is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <sstream> +#include "raul/RDFWorld.h" +#include "raul/RDFModel.h" +#include "raul/RDFNode.h" +#include "raul/AtomRedland.h" + +#define U(x) ((const unsigned char*)(x)) + +using namespace std; + +namespace Raul { +namespace RDF { + + +//static const char* const RDF_LANG = "rdfxml-abbrev"; +static const char* const RDF_LANG = "turtle"; + + +/** Create an empty in-memory RDF model. + */ +Model::Model(RDF::World& world) + : _world(world) + , _serializer(NULL) +{ + _storage = librdf_new_storage(_world.world(), "hashes", NULL, "hash-type='memory'"); + _model = librdf_new_model(_world.world(), _storage, NULL); +} + + +/** Load a model from a URI (local file or remote). + */ +Model::Model(World& world, const Glib::ustring& data_uri) + : _world(world) + , _serializer(NULL) +{ + _storage = librdf_new_storage(_world.world(), "hashes", NULL, "hash-type='memory'"); + _model = librdf_new_model(_world.world(), _storage, NULL); + + librdf_uri* uri = librdf_new_uri(world.world(), (const unsigned char*)data_uri.c_str()); + librdf_parser* parser = librdf_new_parser(world.world(), "guess", NULL, NULL); + librdf_parser_parse_into_model(parser, uri, NULL, _model); + librdf_free_uri(uri); + librdf_free_parser(parser); + + cout << endl << "Loaded model from " << data_uri << ":" << endl; + serialize_to_file_handle(stdout); + cout << endl << endl; +} + + +Model::~Model() +{ + if (_serializer) + librdf_free_serializer(_serializer); + + librdf_free_model(_model); + librdf_free_storage(_storage); +} + + +void +Model::setup_prefixes() +{ + assert(_serializer); + + for (Namespaces::const_iterator i = _world.prefixes().begin(); i != _world.prefixes().end(); ++i) { + librdf_serializer_set_namespace(_serializer, + librdf_new_uri(_world.world(), U(i->second.c_str())), i->first.c_str()); + } +} + + +/** Begin a serialization to a C file handle. + * + * This must be called before any write methods. + */ +void +Model::serialize_to_file_handle(FILE* fd) +{ + _serializer = librdf_new_serializer(_world.world(), RDF_LANG, NULL, NULL); + setup_prefixes(); + librdf_serializer_serialize_model_to_file_handle(_serializer, fd, NULL, _model); + librdf_free_serializer(_serializer); + _serializer = NULL; +} + + +/** Begin a serialization to a file. + * + * This must be called before any write methods. + */ +void +Model::serialize_to_file(const string& filename) +{ + _serializer = librdf_new_serializer(_world.world(), RDF_LANG, NULL, NULL); + setup_prefixes(); + librdf_serializer_serialize_model_to_file(_serializer, filename.c_str(), NULL, _model); + librdf_free_serializer(_serializer); + _serializer = NULL; +} + + +/** Begin a serialization to a string. + * + * This must be called before any write methods. + * + * The results of the serialization will be returned by the finish() method after + * the desired objects have been serialized. + */ +string +Model::serialize_to_string() +{ + _serializer = librdf_new_serializer(_world.world(), RDF_LANG, NULL, NULL); + setup_prefixes(); + + unsigned char* c_str + = librdf_serializer_serialize_model_to_string(_serializer, NULL, _model); + + string result((const char*)c_str); + free(c_str); + + librdf_free_serializer(_serializer); + _serializer = NULL; + + return result; +} + + +void +Model::add_statement(const Node& subject, + const Node& predicate, + const Node& object) +{ + librdf_statement* triple = librdf_new_statement_from_nodes(_world.world(), + subject.get_node(), predicate.get_node(), object.get_node()); + + librdf_model_add_statement(_model, triple); +} + + +void +Model::add_statement(const Node& subject, + const string& predicate_id, + const Node& object) +{ + const string predicate_uri = _world.expand_uri(predicate_id); + librdf_node* predicate = librdf_new_node_from_uri_string(_world.world(), + (const unsigned char*)predicate_uri.c_str()); + + librdf_statement* triple = librdf_new_statement_from_nodes(_world.world(), + subject.get_node(), predicate, object.get_node()); + + librdf_model_add_statement(_model, triple); +} + + +void +Model::add_statement(const Node& subject, + const Node& predicate, + const Atom& object) +{ + librdf_node* atom_node = AtomRedland::atom_to_rdf_node(_world.world(), object); + + if (atom_node) { + librdf_statement* triple = librdf_new_statement_from_nodes(_world.world(), + subject.get_node(), predicate.get_node(), atom_node); + librdf_model_add_statement(_model, triple); + } else { + cerr << "WARNING: Unable to add statement (unserializable Atom)" << endl; + } +} + + +void +Model::add_statement(const Node& subject, + const string& predicate_id, + const Atom& object) +{ + const string predicate_uri = _world.expand_uri(predicate_id); + librdf_node* predicate = librdf_new_node_from_uri_string(_world.world(), + (const unsigned char*)predicate_uri.c_str()); + + librdf_node* atom_node = AtomRedland::atom_to_rdf_node(_world.world(), object); + + if (atom_node) { + librdf_statement* triple = librdf_new_statement_from_nodes(_world.world(), + subject.get_node(), predicate, atom_node); + librdf_model_add_statement(_model, triple); + } else { + cerr << "WARNING: Unable to add statement (unserializable Atom)" << endl; + } +} + + + +} // namespace RDF +} // namespace Raul + diff --git a/src/RDFNode.cpp b/src/RDFNode.cpp new file mode 100644 index 0000000..2278a7a --- /dev/null +++ b/src/RDFNode.cpp @@ -0,0 +1,140 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Raul is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <string> +#include <raul/RDFWorld.h> +#include <raul/RDFNode.h> + +using namespace std; + +namespace Raul { +namespace RDF { + + +Node::Node(World& world, Type type, const std::string& s) +{ + if (type == RESOURCE) + _node = librdf_new_node_from_uri_string(world.world(), (const unsigned char*)s.c_str()); + else if (type == LITERAL) + _node = librdf_new_node_from_literal(world.world(), (const unsigned char*)s.c_str(), NULL, 0); + else if (type == BLANK) + _node = librdf_new_node_from_blank_identifier(world.world(), (const unsigned char*)s.c_str()); + else + _node = NULL; + + assert(this->type() == type); +} + + +Node::Node(World& world) + : _node(librdf_new_node(world.world())) +{ +} + + +Node::Node(librdf_node* node) + : _node(librdf_new_node_from_node(node)) +{ + assert(node); +} + + +Node::Node(const Node& other) + : _node(other._node ? librdf_new_node_from_node(other._node): NULL) +{ +} + + +Node::~Node() +{ + if (_node) + librdf_free_node(_node); +} + + +string +Node::to_string() const +{ + const Type type = this->type(); + if (type == RESOURCE) { + return string((const char*)librdf_uri_as_string(librdf_node_get_uri(_node))); + } else if (type == LITERAL) { + return string((const char*)librdf_node_get_literal_value(_node)); + } else if (type == BLANK) { + return string((const char*)librdf_node_get_blank_identifier(_node)); + } else { + return ""; + } +} + + +string +Node::to_quoted_uri_string() const +{ + assert(type() == RESOURCE); + string str = "<"; + str.append((const char*)librdf_uri_as_string(librdf_node_get_uri(_node))); + str.append(">"); + return str; +} + + +bool +Node::is_int() +{ + if (_node && librdf_node_get_type(_node) == LIBRDF_NODE_TYPE_LITERAL) { + librdf_uri* datatype_uri = librdf_node_get_literal_value_datatype_uri(_node); + if (datatype_uri && !strcmp((const char*)librdf_uri_as_string(datatype_uri), + "http://www.w3.org/2001/XMLSchema#integer")) + return true; + } + return false; +} + + +int +Node::to_int() +{ + assert(is_int()); + return strtol((const char*)librdf_node_get_literal_value(_node), NULL, 10); +} + + +bool +Node::is_float() +{ + if (_node && librdf_node_get_type(_node) == LIBRDF_NODE_TYPE_LITERAL) { + librdf_uri* datatype_uri = librdf_node_get_literal_value_datatype_uri(_node); + if (datatype_uri && !strcmp((const char*)librdf_uri_as_string(datatype_uri), + "http://www.w3.org/2001/XMLSchema#decimal")) + return true; + } + return false; +} + + +float +Node::to_float() +{ + assert(is_float()); + return strtod((const char*)librdf_node_get_literal_value(_node), NULL); +} + + +} // namespace RDF +} // namespace Raul + diff --git a/src/RDFQuery.cpp b/src/RDFQuery.cpp index 90f6c35..2cc2209 100644 --- a/src/RDFQuery.cpp +++ b/src/RDFQuery.cpp @@ -19,65 +19,69 @@ #include <cassert> #include <rasqal.h> #include "raul/RDFQuery.h" +#include "raul/RDFModel.h" using namespace std; namespace Raul { +namespace RDF { -RDFQuery::Results -RDFQuery::run(const Glib::ustring base_uri_str) const +Query::Results +Query::run(World& world, Model& model, const Glib::ustring base_uri_str) const { - Results result; - - rasqal_init(); + //cout << "\n**************** QUERY *******************\n"; + //cout << _query << endl; + //cout << "******************************************\n\n"; - rasqal_query *rq = rasqal_new_query("sparql", NULL); + Results result; - raptor_uri* base_uri = NULL; + librdf_uri* base_uri = NULL; if (base_uri_str != "") - base_uri = raptor_new_uri((const unsigned char*)base_uri_str.c_str()); - rasqal_query_prepare(rq, (unsigned char*)_query.c_str(), base_uri); + base_uri = librdf_new_uri(world.world(), + (const unsigned char*)base_uri_str.c_str()); - rasqal_query_results* results = rasqal_query_execute(rq); + librdf_query* q = librdf_new_query(world.world(), "sparql", + NULL, (unsigned char*)_query.c_str(), base_uri); + + if (!q) { + cerr << "Unable to create query:" << endl << _query << endl; + return result; /* Return an empty Results */ + } + + librdf_query_results* results = librdf_query_execute(q, model._model); if (!results) { - cerr << "Failed Query was:" << endl << _query << endl; + cerr << "Failed query:" << endl << _query << endl; return result; /* Return an empty Results */ } - while (!rasqal_query_results_finished(results)) { + while (!librdf_query_results_finished(results)) { Bindings bindings; - for (int i=0; i < rasqal_query_results_get_bindings_count(results); i++) { - const unsigned char* rname = rasqal_query_results_get_binding_name(results, i); - rasqal_literal* rvalue = rasqal_query_results_get_binding_value(results, i); - Glib::ustring name((const char*)rname); + for (int i=0; i < librdf_query_results_get_bindings_count(results); i++) { + const char* name = (char*)librdf_query_results_get_binding_name(results, i); + librdf_node* value = librdf_query_results_get_binding_value(results, i); - const unsigned char* str = rasqal_literal_as_string(rvalue); - - if (str) { - Glib::ustring value((const char*)str); - bindings.insert(std::make_pair(name, value)); - } + if (name && value) + bindings.insert(std::make_pair(std::string(name), Node(value))); } result.push_back(bindings); - rasqal_query_results_next(results); + librdf_query_results_next(results); } - rasqal_free_query_results(results); - rasqal_free_query(rq); + librdf_free_query_results(results); + librdf_free_query(q); if (base_uri) - raptor_free_uri(base_uri); - - rasqal_finish(); + librdf_free_uri(base_uri); return result; } +} // namespace RDF } // namespace Raul diff --git a/src/RDFWorld.cpp b/src/RDFWorld.cpp new file mode 100644 index 0000000..caf6fb8 --- /dev/null +++ b/src/RDFWorld.cpp @@ -0,0 +1,95 @@ +/* This file is part of Raul. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Raul is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Raul is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <sstream> +#include "raul/RDFWorld.h" +#include "raul/RDFNode.h" +#include "raul/AtomRedland.h" + +#define U(x) ((const unsigned char*)(x)) + +using namespace std; + +namespace Raul { +namespace RDF { + + +//static const char* const RDF_LANG = "rdfxml-abbrev"; +static const char* const RDF_LANG = "turtle"; + + +/** Create an empty in-memory RDF model. + */ +World::World() +{ + _world = librdf_new_world(); + assert(_world); + librdf_world_open(_world); + + add_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); +} + + +World::~World() +{ + librdf_free_world(_world); +} + + +void +World::add_prefix(const string& prefix, const string& uri) +{ + _prefixes[prefix] = uri; +} + + +/** Expands the prefix of URI, if the prefix is registered. + */ +string +World::expand_uri(const string& uri) const +{ + assert(uri.find(":") != string::npos); + + for (Namespaces::const_iterator i = _prefixes.begin(); i != _prefixes.end(); ++i) + if (uri.substr(0, i->first.length()+1) == i->first + ":") + return i->second + uri.substr(i->first.length()+1); + + return uri; +} + + +/** Opposite of expand_uri + */ +string +World::qualify(const string& uri) const +{ + return _prefixes.qualify(uri); +} + + +Node +World::blank_id() +{ + std::ostringstream ss; + ss << "n" << _next_blank_id++; + return Node(*this, Node::BLANK, ss.str()); +} + + +} // namespace RDF +} // namespace Raul + diff --git a/src/RDFWriter.cpp b/src/RDFWriter.cpp deleted file mode 100644 index d6a33a4..0000000 --- a/src/RDFWriter.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* This file is part of Raul. - * Copyright (C) 2007 Dave Robillard <http://drobilla.net> - * - * Raul is free software; you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) any later - * version. - * - * Raul is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <sstream> -#include "raul/RDFWriter.h" -#include "raul/AtomRaptor.h" - -#define U(x) ((const unsigned char*)(x)) - -using namespace std; - -namespace Raul { - - -//static const char* const RDF_LANG = "rdfxml-abbrev"; -static const char* const RDF_LANG = "turtle"; - - -RDFWriter::RDFWriter() - : _serializer(NULL) - , _string_output(NULL) - , _next_blank_id(0) -{ - add_prefix("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#"); -} - - -void -RDFWriter::add_prefix(const string& prefix, const string& uri) -{ - _prefixes[prefix] = uri; - if (_serializer) - raptor_serialize_set_namespace(_serializer, - raptor_new_uri(U(uri.c_str())), U(prefix.c_str())); -} - - -void -RDFWriter::setup_prefixes() -{ - assert(_serializer); - - for (Namespaces::const_iterator i = _prefixes.begin(); i != _prefixes.end(); ++i) { - raptor_serialize_set_namespace(_serializer, - raptor_new_uri(U(i->second.c_str())), U(i->first.c_str())); - } -} - - -/** Expands the prefix of URI, if the prefix is registered. - */ -string -RDFWriter::expand_uri(const string& uri) -{ - for (Namespaces::const_iterator i = _prefixes.begin(); i != _prefixes.end(); ++i) - if (uri.substr(0, i->first.length()+1) == i->first + ":") - return i->second + uri.substr(i->first.length()+1); - - return uri; -} - - -RdfId -RDFWriter::blank_id() -{ - std::ostringstream ss; - ss << "n" << _next_blank_id++; - return RdfId(RdfId::ANONYMOUS, ss.str()); -} - - -/** Begin a serialization to a C file handle. - * - * This must be called before any write methods. - */ -void -RDFWriter::start_to_file_handle(FILE* fd) throw (std::logic_error) -{ - if (_serializer) - throw std::logic_error("start_to_string called with serialization in progress"); - - raptor_init(); - _serializer = raptor_new_serializer(RDF_LANG); - raptor_serialize_start_to_file_handle(_serializer, NULL, fd); - setup_prefixes(); -} - - -/** Begin a serialization to a file. - * - * This must be called before any write methods. - */ -void -RDFWriter::start_to_filename(const string& filename) throw (std::logic_error) -{ - if (_serializer) - throw std::logic_error("start_to_string called with serialization in progress"); - - raptor_init(); - _serializer = raptor_new_serializer(RDF_LANG); - raptor_serialize_start_to_filename(_serializer, filename.c_str()); - setup_prefixes(); -} - - -/** Begin a serialization to a string. - * - * This must be called before any write methods. - * - * The results of the serialization will be returned by the finish() method after - * the desired objects have been serialized. - */ -void -RDFWriter::start_to_string() throw (std::logic_error) -{ - if (_serializer) - throw std::logic_error("start_to_string called with serialization in progress"); - - raptor_init(); - _serializer = raptor_new_serializer(RDF_LANG); - raptor_serialize_start_to_string(_serializer, - NULL /*base_uri*/, - (void**)&_string_output, - NULL /*size*/); - setup_prefixes(); -} - - -/** Finish a serialization. - * - * If this was a serialization to a string, the serialization output - * will be returned, otherwise the empty string is returned. - */ -string -RDFWriter::finish() throw(std::logic_error) -{ - string ret = ""; - - if (!_serializer) - throw std::logic_error("finish() called with no serialization in progress"); - - raptor_serialize_end(_serializer); - - if (_string_output) { - ret = string((char*)_string_output); - free(_string_output); - _string_output = NULL; - } - - raptor_free_serializer(_serializer); - _serializer = NULL; - - raptor_finish(); - - return ret; -} - - -void -RDFWriter::write(const RdfId& subject, - const RdfId& predicate, - const RdfId& object) -{ - assert(_serializer); - - raptor_statement triple; - - // FIXME: leaks? - - if (subject.type() == RdfId::RESOURCE) { - triple.subject = (void*)raptor_new_uri((const unsigned char*) - expand_uri(subject.to_string()).c_str()); - triple.subject_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE; - } else { - assert(subject.type() == RdfId::ANONYMOUS); - triple.subject = (unsigned char*)(strdup(subject.to_string().c_str())); - triple.subject_type = RAPTOR_IDENTIFIER_TYPE_ANONYMOUS; - } - - assert(predicate.type() == RdfId::RESOURCE); - triple.predicate = (void*)raptor_new_uri((const unsigned char*) - expand_uri(predicate.to_string()).c_str()); - triple.predicate_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE; - - if (object.type() == RdfId::RESOURCE) { - triple.object = (void*)raptor_new_uri((const unsigned char*) - expand_uri(object.to_string()).c_str()); - triple.object_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE; - } else { - assert(object.type() == RdfId::ANONYMOUS); - triple.object = (unsigned char*)(strdup(object.to_string().c_str())); - triple.object_type = RAPTOR_IDENTIFIER_TYPE_ANONYMOUS; - } - - raptor_serialize_statement(_serializer, &triple); - - if (subject.type() == RdfId::RESOURCE) - raptor_free_uri((raptor_uri*)triple.subject); - - raptor_free_uri((raptor_uri*)triple.predicate); - - if (object.type() == RdfId::RESOURCE) - raptor_free_uri((raptor_uri*)triple.object); -} - - -void -RDFWriter::write(const RdfId& subject, - const RdfId& predicate, - const Atom& object) -{ - assert(_serializer); - - raptor_statement triple; - - if (subject.type() == RdfId::RESOURCE) { - triple.subject = (void*)raptor_new_uri((const unsigned char*) - expand_uri(subject.to_string()).c_str()); - triple.subject_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE; - } else { - assert(subject.type() == RdfId::ANONYMOUS); - triple.subject = (unsigned char*)(strdup(subject.to_string().c_str())); - triple.subject_type = RAPTOR_IDENTIFIER_TYPE_ANONYMOUS; - } - - assert(predicate.type() == RdfId::RESOURCE); - triple.predicate = (void*)raptor_new_uri((const unsigned char*) - expand_uri(predicate.to_string()).c_str()); - triple.predicate_type = RAPTOR_IDENTIFIER_TYPE_RESOURCE; - - AtomRaptor::atom_to_triple_object(&triple, object); - - raptor_serialize_statement(_serializer, &triple); - - if (subject.type() == RdfId::RESOURCE) - raptor_free_uri((raptor_uri*)triple.subject); - - raptor_free_uri((raptor_uri*)triple.predicate); -} - - -} // namespace Raul - diff --git a/tests/Makefile.am b/tests/Makefile.am index af2b7f4..8347d39 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ if BUILD_TESTS -AM_CXXFLAGS = -I.. -lpthread @RASQAL_CFLAGS@ @GLIBMM_CFLAGS@ -ALL_LIBS = @RASQAL_LIBS@ @GLIBMM_LIBS@ ../src/libraul.la +AM_CXXFLAGS = -I.. -lpthread @REDLAND_CFLAGS@ @GLIBMM_CFLAGS@ +ALL_LIBS = @REDLAND_LIBS@ @GLIBMM_LIBS@ ../src/libraul.la bin_PROGRAMS = \ path_test \ @@ -13,7 +13,8 @@ bin_PROGRAMS = \ list_test \ time_test \ quantize_test \ - smf_test + smf_test \ + rdf_test thread_test_LDADD = $(ALL_LIBS) path_test_LDADD = $(ALL_LIBS) @@ -25,6 +26,7 @@ list_test_LDADD = $(ALL_LIBS) time_test_LDADD = $(ALL_LIBS) quantize_test_LDADD = $(ALL_LIBS) smf_test_LDADD = $(ALL_LIBS) +rdf_test_LDADD = $(ALL_LIBS) path_test_SOURCES = path_test.cpp thread_test_SOURCES = thread_test.cpp @@ -36,5 +38,6 @@ list_test_SOURCES = list_test.cpp time_test_SOURCES = time_test.cpp quantize_test_SOURCES = quantize_test.cpp smf_test_SOURCES = smf_test.cpp +rdf_test_SOURCES = rdf_test.cpp endif diff --git a/tests/rdf_test.cpp b/tests/rdf_test.cpp new file mode 100644 index 0000000..6e224cf --- /dev/null +++ b/tests/rdf_test.cpp @@ -0,0 +1,8 @@ +#include <raul/RDFModel.h> +#include <raul/RDFQuery.h> + +int +main() +{ + return 0; +} |