diff options
author | David Robillard <d@drobilla.net> | 2008-08-17 06:38:33 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-08-17 06:38:33 +0000 |
commit | 03acefb8271d2abb5160b349d8e70687af6965fb (patch) | |
tree | e377017141707b2a97eeda4adffcfbb56eec88bc /src/libs/serialisation | |
parent | 696535322342c56901d4d48641b6f9cf816ac1e1 (diff) | |
download | ingen-03acefb8271d2abb5160b349d8e70687af6965fb.tar.gz ingen-03acefb8271d2abb5160b349d8e70687af6965fb.tar.bz2 ingen-03acefb8271d2abb5160b349d8e70687af6965fb.zip |
Clean up parser into generic form that can parse anything (rather than just the root patch from a document).
Support for parsing from a string.
Fix serialisation to a string.
git-svn-id: http://svn.drobilla.net/lad/ingen@1414 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/libs/serialisation')
-rw-r--r-- | src/libs/serialisation/Parser.cpp | 214 | ||||
-rw-r--r-- | src/libs/serialisation/Parser.hpp | 54 | ||||
-rw-r--r-- | src/libs/serialisation/Serialiser.cpp | 34 | ||||
-rw-r--r-- | src/libs/serialisation/Serialiser.hpp | 4 |
4 files changed, 217 insertions, 89 deletions
diff --git a/src/libs/serialisation/Parser.cpp b/src/libs/serialisation/Parser.cpp index cd132b3a..b34a3e47 100644 --- a/src/libs/serialisation/Parser.cpp +++ b/src/libs/serialisation/Parser.cpp @@ -20,6 +20,7 @@ #include <locale.h> #include <glibmm/ustring.h> #include <redlandmm/Model.hpp> +#include <redlandmm/Node.hpp> #include <redlandmm/Query.hpp> #include <raul/TableImpl.hpp> #include <raul/Atom.hpp> @@ -34,6 +35,8 @@ using namespace Ingen::Shared; namespace Ingen { namespace Serialisation { +#define NS_INGEN "http://drobilla.net/ns/ingen#" + /** Parse a patch from RDF into a CommonInterface (engine or client). * @@ -42,42 +45,145 @@ namespace Serialisation { * @return whether or not load was successful. */ bool -Parser::parse(Ingen::Shared::World* world, - Ingen::Shared::CommonInterface* target, - const Glib::ustring& document_uri, - boost::optional<Raul::Path> parent, - std::string patch_name, - Glib::ustring patch_uri, - GraphObject::Variables data) +Parser::parse_document( + Ingen::Shared::World* world, + Ingen::Shared::CommonInterface* target, + const Glib::ustring& document_uri, + Glib::ustring object_uri, + boost::optional<Raul::Path> parent, + boost::optional<Raul::Symbol> symbol, + boost::optional<GraphObject::Variables> data) { - setlocale(LC_NUMERIC, "C"); + Redland::Model model(*world->rdf_world, document_uri, document_uri); - // FIXME: this whole thing is a mess + if (object_uri == "") { + object_uri = string("<") + document_uri + ">"; + cout << "[Parser] Parsing document " << object_uri << endl; + } else { + object_uri = string("<") + object_uri + ">"; + cout << "[Parser] Parsing " << object_uri << " from " << document_uri << endl; + } - std::set<Path> created; + return parse(world, target, model, document_uri, object_uri, parent, symbol, data);; +} - Redland::Model model(*world->rdf_world, document_uri, document_uri); - if (patch_uri == "") - patch_uri = string("<") + document_uri + ">"; - else - patch_uri = string("<") + patch_uri + ">"; +bool +Parser::parse_string( + Ingen::Shared::World* world, + Ingen::Shared::CommonInterface* target, + const Glib::ustring& str, + const Glib::ustring& base_uri, + Glib::ustring object_uri, + boost::optional<Raul::Path> parent, + boost::optional<Raul::Symbol> symbol, + boost::optional<GraphObject::Variables> data) +{ + Redland::Model model(*world->rdf_world, str.c_str(), str.length(), base_uri); + + if (object_uri == "") { + object_uri = string("<") + base_uri + ">"; + cout << "[Parser] Parsing document " << object_uri << endl; + } else { + object_uri = string("<") + object_uri + ">"; + cout << "[Parser] Parsing " << object_uri << " from string" << endl; + } + + return parse(world, target, model, base_uri, object_uri, parent, symbol, data);; +} + + +bool +Parser::parse( + Ingen::Shared::World* world, + Ingen::Shared::CommonInterface* target, + Redland::Model& model, + const Glib::ustring& base_uri, + Glib::ustring object_uri, + boost::optional<Raul::Path> parent, + boost::optional<Raul::Symbol> symbol, + boost::optional<GraphObject::Variables> data) +{ + Redland::Query query(*world->rdf_world, Glib::ustring( + "SELECT DISTINCT ?class WHERE { ") + object_uri + " a ?class . }"); + + Redland::Query::Results results = query.run(*world->rdf_world, model); + + const Redland::Node patch_class(*world->rdf_world, Redland::Node::RESOURCE, NS_INGEN "Patch"); + const Redland::Node node_class(*world->rdf_world, Redland::Node::RESOURCE, NS_INGEN "Node"); + const Redland::Node port_class(*world->rdf_world, Redland::Node::RESOURCE, NS_INGEN "Port"); + + for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { + const Redland::Node rdf_class = (*i)["class"]; + if (rdf_class == patch_class || rdf_class == node_class || rdf_class == port_class) { + Path path = parse_path(world, model, base_uri, object_uri, parent, symbol); + bool ret = false; + if (rdf_class == patch_class) { + ret = parse_patch(world, target, model, object_uri, path, data); + if (ret) + target->set_variable(path, "ingen:document", Atom(base_uri.c_str())); + } else if (rdf_class == node_class) { + cout << "NODE" << endl; + } else if (rdf_class == port_class) { + cout << "PORT" << endl; + } + return ret; + } + } + + return false; +} - cout << "[Parser] Loading " << patch_uri << endl; - size_t patch_poly = 1; +Path +Parser::parse_path(Ingen::Shared::World* world, + Redland::Model& model, + const Glib::ustring& base_uri, + const Glib::ustring& object_uri, + boost::optional<Raul::Path>& parent, + boost::optional<Raul::Symbol>& symbol) +{ + Redland::Query query(*world->rdf_world, Glib::ustring( + "SELECT DISTINCT ?sym WHERE { ") + object_uri + " ingen:symbol ?sym }"); + Redland::Query::Results results = query.run(*world->rdf_world, model); + if (results.size() > 0) { + symbol = (*results.begin())["sym"].to_string(); + } else { + const string sym = base_uri.substr(base_uri.find_last_of("/")+1); + symbol = sym.substr(0, sym.find(".")); + } + + Path ret = (parent ? (parent.get().base() + symbol.get()) : Path("/")); + cout << "Parsing " << object_uri << " from " << base_uri << " as " << ret << endl; + return ret; +} + + +bool +Parser::parse_patch( + Ingen::Shared::World* world, + Ingen::Shared::CommonInterface* target, + Redland::Model& model, + const Glib::ustring& object_uri, + Raul::Path patch_path, + boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>()) +{ + std::set<Path> created; + uint32_t patch_poly = 0; + /* Use parameter overridden polyphony, if given */ - GraphObject::Variables::iterator poly_param = data.find("ingen:polyphony"); - if (poly_param != data.end() && poly_param->second.type() == Atom::INT) { - patch_poly = poly_param->second.get_int32(); + if (data) { + GraphObject::Variables::iterator poly_param = data.get().find("ingen:polyphony"); + if (poly_param != data.get().end() && poly_param->second.type() == Atom::INT) + patch_poly = poly_param->second.get_int32(); + } /* Get polyphony from file (mandatory if not specified in parameters) */ - } else { - // FIXME: polyphony datatype? + if (patch_poly == 0) { Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?poly WHERE {\n") + - patch_uri + " ingen:polyphony ?poly\n }"); + object_uri + " ingen:polyphony ?poly\n }"); Redland::Query::Results results = query.run(*world->rdf_world, model); @@ -88,42 +194,21 @@ Parser::parse(Ingen::Shared::World* world, const Redland::Node& poly_node = (*results.begin())["poly"]; assert(poly_node.is_int()); - patch_poly = static_cast<size_t>(poly_node.to_int()); + patch_poly = static_cast<uint32_t>(poly_node.to_int()); } - /* Get name (if available/necessary) */ - - if (patch_name == "") { - patch_name = string(document_uri.substr(document_uri.find_last_of("/")+1)); - if (patch_name.substr(patch_name.length()-10) == ".ingen.ttl") - patch_name = patch_name.substr(0, patch_name.length()-10); - - Redland::Query query(*world->rdf_world, Glib::ustring( - "SELECT DISTINCT ?name WHERE {\n") + - patch_uri + " ingen:symbol ?name\n}"); - - Redland::Query::Results results = query.run(*world->rdf_world, model); - - if (results.size() > 0) - patch_name = (*results.begin())["name"].to_string(); - } - - const Path patch_path = ( parent ? (parent.get().base() + patch_name) : Path("/") ); - - cout << " as " << patch_path << endl; - if (patch_path != "/") target->new_patch(patch_path, patch_poly); /* Set document metadata (so File->Save doesn't prompt) * FIXME: This needs some thinking for multiple clients... */ - target->set_variable(patch_path, "ingen:document", Atom(document_uri.c_str())); + /* Load (plugin) nodes */ Redland::Query query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?name ?plugin ?varkey ?varval ?poly WHERE {\n") + - patch_uri + " ingen:node ?node .\n" + object_uri + " ingen:node ?node .\n" "?node ingen:symbol ?name ;\n" " ingen:plugin ?plugin ;\n" " ingen:polyphonic ?poly .\n" @@ -170,24 +255,24 @@ Parser::parse(Ingen::Shared::World* world, /* Load subpatches */ query = Redland::Query(*world->rdf_world, Glib::ustring( - "SELECT DISTINCT ?patch ?name WHERE {\n") + - patch_uri + " ingen:node ?patch .\n" + "SELECT DISTINCT ?patch ?symbol WHERE {\n") + + object_uri + " ingen:node ?patch .\n" "?patch a ingen:Patch ;\n" - " ingen:symbol ?name .\n" + " ingen:symbol ?symbol .\n" "}"); results = query.run(*world->rdf_world, model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - const string name = (*i)["name"].to_string(); - const string patch = (*i)["patch"].to_string(); + const string symbol = (*i)["symbol"].to_string(); + const string patch = (*i)["patch"].to_string(); - const Path subpatch_path = patch_path.base() + (string)name; + const Path subpatch_path = patch_path.base() + symbol; if (created.find(subpatch_path) == created.end()) { created.insert(subpatch_path); - parse(world, target, document_uri, patch_path, name, patch); + parse_patch(world, target, model, Glib::ustring(object_uri + subpatch_path), subpatch_path); } } @@ -198,7 +283,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?nodename ?portname ?portval WHERE {\n") + - patch_uri + " ingen:node ?node .\n" + object_uri + " ingen:node ?node .\n" "?node ingen:symbol ?nodename ;\n" " ingen:port ?port .\n" "?port ingen:symbol ?portname ;\n" @@ -225,7 +310,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?port ?type ?name ?datatype ?varkey ?varval ?portval WHERE {\n") + - patch_uri + " ingen:port ?port .\n" + object_uri + " ingen:port ?port .\n" "?port a ?type ;\n" " a ?datatype ;\n" " ingen:symbol ?name .\n" @@ -272,7 +357,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcnodename ?srcname ?dstnodename ?dstname WHERE {\n") + - patch_uri + "ingen:node ?srcnode ;\n" + object_uri + "ingen:node ?srcnode ;\n" " ingen:node ?dstnode .\n" "?srcnode ingen:port ?src ;\n" " ingen:symbol ?srcnodename .\n" @@ -301,7 +386,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcname ?dstnodename ?dstname WHERE {\n") + - patch_uri + " ingen:port ?src ;\n" + object_uri + " ingen:port ?src ;\n" " ingen:node ?dstnode .\n" "?dstnode ingen:port ?dst ;\n" " ingen:symbol ?dstnodename .\n" @@ -327,7 +412,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcnodename ?srcname ?dstname WHERE {\n") + - patch_uri + " ingen:port ?dst ;\n" + object_uri + " ingen:port ?dst ;\n" " ingen:node ?srcnode .\n" "?srcnode ingen:port ?src ;\n" " ingen:symbol ?srcnodename .\n" @@ -353,7 +438,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?srcname ?dstname WHERE {\n") + - patch_uri + " ingen:port ?src ;\n" + object_uri + " ingen:port ?src ;\n" " ingen:port ?dst .\n" "?dst ingen:connectedTo ?src ;\n" " ingen:symbol ?dstname .\n" @@ -376,7 +461,7 @@ Parser::parse(Ingen::Shared::World* world, query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?varkey ?varval WHERE {\n") + - patch_uri + " ingen:variable ?variable .\n" + object_uri + " ingen:variable ?variable .\n" "?variable ingen:key ?varkey ;\n" " ingen:value ?varval .\n" "}"); @@ -394,15 +479,16 @@ Parser::parse(Ingen::Shared::World* world, // Set passed variables last to override any loaded values - for (GraphObject::Variables::const_iterator i = data.begin(); i != data.end(); ++i) - target->set_variable(patch_path, i->first, i->second); + if (data) + for (GraphObject::Variables::const_iterator i = data.get().begin(); i != data.get().end(); ++i) + target->set_variable(patch_path, i->first, i->second); /* Enable */ query = Redland::Query(*world->rdf_world, Glib::ustring( "SELECT DISTINCT ?enabled WHERE {\n") + - patch_uri + " ingen:enabled ?enabled .\n" + object_uri + " ingen:enabled ?enabled .\n" "}"); results = query.run(*world->rdf_world, model); diff --git a/src/libs/serialisation/Parser.hpp b/src/libs/serialisation/Parser.hpp index 18d59bf2..2aaf3bfb 100644 --- a/src/libs/serialisation/Parser.hpp +++ b/src/libs/serialisation/Parser.hpp @@ -27,7 +27,7 @@ #include "interface/GraphObject.hpp" #include "module/World.hpp" -namespace Redland { class World; } +namespace Redland { class World; class Model; } namespace Ingen { namespace Shared { class CommonInterface; } } using namespace Ingen::Shared; @@ -40,13 +40,51 @@ class Parser { public: virtual ~Parser() {} - virtual bool parse(Ingen::Shared::World* world, - Ingen::Shared::CommonInterface* target, - const Glib::ustring& uri, - boost::optional<Raul::Path> parent, - std::string patch_name, - Glib::ustring patch_uri = "", - GraphObject::Variables data = GraphObject::Variables()); + virtual bool parse_document( + Ingen::Shared::World* world, + Shared::CommonInterface* target, + const Glib::ustring& document_uri, + Glib::ustring object_uri, + boost::optional<Raul::Path> parent=boost::optional<Raul::Path>(), + boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(), + boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>()); + + virtual bool parse_string( + Ingen::Shared::World* world, + Shared::CommonInterface* target, + const Glib::ustring& str, + const Glib::ustring& base_uri, + Glib::ustring object_uri, + boost::optional<Raul::Path> parent=boost::optional<Raul::Path>(), + boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(), + boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>()); + +private: + bool parse( + Ingen::Shared::World* world, + Shared::CommonInterface* target, + Redland::Model& model, + const Glib::ustring& base_uri, + Glib::ustring object_uri, + boost::optional<Raul::Path> parent=boost::optional<Raul::Path>(), + boost::optional<Raul::Symbol> symbol=boost::optional<Raul::Symbol>(), + boost::optional<GraphObject::Variables> data=boost::optional<GraphObject::Variables>()); + + Raul::Path parse_path( + Ingen::Shared::World* world, + Redland::Model& model, + const Glib::ustring& base_uri, + const Glib::ustring& object_uri, + boost::optional<Raul::Path>& parent, + boost::optional<Raul::Symbol>& symbol); + + bool parse_patch( + Ingen::Shared::World* world, + Ingen::Shared::CommonInterface* target, + Redland::Model& model, + const Glib::ustring& object_uri, + Raul::Path path, + boost::optional<GraphObject::Variables> data); }; diff --git a/src/libs/serialisation/Serialiser.cpp b/src/libs/serialisation/Serialiser.cpp index d2f2031f..a56d6add 100644 --- a/src/libs/serialisation/Serialiser.cpp +++ b/src/libs/serialisation/Serialiser.cpp @@ -54,15 +54,17 @@ namespace Serialisation { Serialiser::Serialiser(Shared::World& world, SharedPtr<Shared::Store> store) - : _store(store) + : _root_path("/") + , _store(store) , _world(*world.rdf_world) { } + void Serialiser::to_file(SharedPtr<GraphObject> object, const string& filename) { - _root_object = object; + _root_path = object->path(); start_to_filename(filename); serialise(object); finish(); @@ -75,8 +77,8 @@ Serialiser::to_string(SharedPtr<GraphObject> object, const string& base_uri, const GraphObject::Variables& extra_rdf) { - _root_object = object; - start_to_string(base_uri); + _root_path = object->path(); + start_to_string(object->path(), base_uri); serialise(object); Redland::Node base_rdf_node(_model->world(), Redland::Node::RESOURCE, base_uri); @@ -121,7 +123,7 @@ Serialiser::start_to_filename(const string& filename) * the desired objects have been serialised. */ void -Serialiser::start_to_string(const string& base_uri) +Serialiser::start_to_string(const Raul::Path& root, const string& base_uri) { setlocale(LC_NUMERIC, "C"); @@ -141,11 +143,13 @@ string Serialiser::finish() { string ret = ""; - - if (_mode == TO_FILE) + if (_mode == TO_FILE) { _model->serialise_to_file(_base_uri); - else - ret = _model->serialise_to_string(); + } else { + char* c_str = _model->serialise_to_string(); + ret = c_str; + free(c_str); + } _base_uri = ""; #ifdef USE_BLANK_NODES @@ -159,12 +163,12 @@ Redland::Node Serialiser::patch_path_to_rdf_node(const Path& path) { #ifdef USE_BLANK_NODES - if (path == _root_object->path()) { + if (path == _root_path) { return Redland::Node(_model->world(), Redland::Node::RESOURCE, _base_uri); } else { - assert(path.length() > _root_object->path().length()); + assert(path.length() > _root_path.length()); return Redland::Node(_model->world(), Redland::Node::RESOURCE, - _base_uri + string("#") + path.substr(_root_object->path().length())); + _base_uri + string("#") + path.substr(_root_path.length())); } #else return path_to_rdf_node(path); @@ -192,13 +196,13 @@ Serialiser::path_to_rdf_node(const Path& path) } #else assert(_model); - assert(path.substr(0, _root_object->path().length()) == _root_object->path()); + assert(path.substr(0, _root_path.length()) == _root_path); - if (path == _root_object->path()) + if (path == _root_path) return Redland::Node(_model->world(), Redland::Node::RESOURCE, _base_uri); else return Redland::Node(_model->world(), Redland::Node::RESOURCE, - path.substr(_root_object->path().base().length()-1)); + path.substr(_root_path.base().length())); #endif } diff --git a/src/libs/serialisation/Serialiser.hpp b/src/libs/serialisation/Serialiser.hpp index 5810f259..1c7271d2 100644 --- a/src/libs/serialisation/Serialiser.hpp +++ b/src/libs/serialisation/Serialiser.hpp @@ -64,7 +64,7 @@ public: const std::string& base_uri, const GraphObject::Variables& extra_rdf); - void start_to_string(const std::string& base_uri); + void start_to_string(const Raul::Path& root, const std::string& base_uri); void serialise(SharedPtr<GraphObject> object) throw (std::logic_error); void serialise_connection(SharedPtr<Shared::Connection> c) throw (std::logic_error); @@ -88,7 +88,7 @@ private: Redland::Node path_to_rdf_node(const Path& path); Redland::Node patch_path_to_rdf_node(const Path& path); - SharedPtr<GraphObject> _root_object; + Raul::Path _root_path; SharedPtr<Shared::Store> _store; Mode _mode; std::string _base_uri; |