summaryrefslogtreecommitdiffstats
path: root/src/libs/serialisation
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-08-17 06:38:33 +0000
committerDavid Robillard <d@drobilla.net>2008-08-17 06:38:33 +0000
commit03acefb8271d2abb5160b349d8e70687af6965fb (patch)
treee377017141707b2a97eeda4adffcfbb56eec88bc /src/libs/serialisation
parent696535322342c56901d4d48641b6f9cf816ac1e1 (diff)
downloadingen-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.cpp214
-rw-r--r--src/libs/serialisation/Parser.hpp54
-rw-r--r--src/libs/serialisation/Serialiser.cpp34
-rw-r--r--src/libs/serialisation/Serialiser.hpp4
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;